C ++多态性中的访问冲突(指向错误位置的虚拟指针函数?)
Access violation in C++ polymorphism (virtual pointer function pointing to wrong place?)
这越来越奇怪了。 Ship 继承自Entity,MerchantShip 继承自Ship,其他类型待补,但基本思路,教授问的是,我使用多态,这样我就可以在main class(分配内存的指针在我的实现中用作数组),因此在后面的所有三个 classes 中都有一个 virtual void 更新。事实上,我已经使用了所有可能有意义的虚函数和非虚函数的组合。代码:
#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
using namespace std;
class Entity
{
public:
int x, y;
virtual void update() = 0;
void print()
{
cout << "x:" << x << ", y:" << y << endl;
}
};
class Ship: public Entity
{
public:
virtual void update()
{
Move();
}
void Move(){x++;};
};
class MerchantShip: public Ship
{
public:
void update()
{
DontMove();
}
void DontMove(){};
};
int main(int argc, char* argv[])
{
int EntityNumber = 2;
Entity* entities;
entities = (Entity*)malloc(EntityNumber*sizeof(Entity));
for (int i = 0; i < EntityNumber; i++)
{
entities[i].print();
entities[i].update();
entities[i].print();
cout << endl << "next ship: " << endl;
}
system("PAUSE");
return 0;
}
好的,所以它编译得很好(stdafx.h 仅在 Visual Studio 中需要)但是我收到一个运行时错误,这是在它试图进入被覆盖的更新函数时在 0xffffffffffffffff 处的访问冲突。在调试信息中,它始终看起来像虚函数指针 (__vfptr) 明显指向其他地方而不是它应该在的地方 (0xcdcdcdcdcdcdcdcd),而且它总是相同的位置,即使在另一个代码中我试图做同样的事情.
目前研究:
原因 #1(不适用):在调用前释放的 DLL 中使用函数
原因#2(再次不适用):程序员忘记继承。
我没有在任何具有相同问题的线程中遇到任何其他问题,并且我已经调试了几天。如果我删除覆盖,它只会调用 Base class 的函数。
有什么线索吗?
您不应使用 malloc
分配 C++ 对象。 new
是正确的运算符。
您将无法实例化 Entity
,因为它是一个抽象 class。
你需要的是指向 Entity
的指针数组,并将它们关联到具体 Entity
(Ship
或 MerchantShip
)的地址,如下所示:
typedef Entity *PEntity;
PEntity entities[2];
entities[0] = new Ship();
entities[1] = new MerchantShip();
当您通过指针调用虚方法时,多态性将正确应用:
for (int i=0; i<2; i++) {
entities[i]->print();
entities[i]->update();
entities[i]->print();
}
真正重要的是要明白这里没有Entity
,只有具体的Entity
。 Entity
只是一个概念; Ship
(或MerchantShip
)是其具体实现之一。您可以通过它们的抽象接口来操作具体对象。
malloc
不创建和初始化对象,只是保留一块内存。在 C++ 中,您应该远离手动分配的动态数组并使用 std::vector
而不是
#include "stdafx.h"
// these headers are discouraged. Use cstdlib and cstdio instead.
//#include <stdlib.h>
//#include <stdio.h>
#include <iostream>
#include <vector>
#include <memory>
using namespace std;
class Entity
{
public:
int x, y;
virtual void update() = 0;
void print()
{
cout << "x:" << x << ", y:" << y << endl;
}
virtual ~Entity() {} // any base-class should have this
};
class Ship: public Entity
{
public:
virtual void update()
{
Move();
}
void Move(){x++;};
};
class MerchantShip: public Ship
{
public:
void update()
{
DontMove();
}
void DontMove(){};
};
int main(int argc, char* argv[])
{
int EntityNumber = 2;
std::vector<std::unique_ptr<Entity>> entities(EntityNumber);
// the array is empty so you have to create some objects in it
entities[0] = new MerchantShip;
entities[1] = new Ship;
for (int i = 0; i < EntityNumber; i++)
{
entities[i].print();
entities[i].update();
entities[i].print();
cout << endl << "next ship: " << endl;
}
system("PAUSE");
return 0;
}
我还在你的基础上添加了一个虚拟析构函数class。
这越来越奇怪了。 Ship 继承自Entity,MerchantShip 继承自Ship,其他类型待补,但基本思路,教授问的是,我使用多态,这样我就可以在main class(分配内存的指针在我的实现中用作数组),因此在后面的所有三个 classes 中都有一个 virtual void 更新。事实上,我已经使用了所有可能有意义的虚函数和非虚函数的组合。代码:
#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
using namespace std;
class Entity
{
public:
int x, y;
virtual void update() = 0;
void print()
{
cout << "x:" << x << ", y:" << y << endl;
}
};
class Ship: public Entity
{
public:
virtual void update()
{
Move();
}
void Move(){x++;};
};
class MerchantShip: public Ship
{
public:
void update()
{
DontMove();
}
void DontMove(){};
};
int main(int argc, char* argv[])
{
int EntityNumber = 2;
Entity* entities;
entities = (Entity*)malloc(EntityNumber*sizeof(Entity));
for (int i = 0; i < EntityNumber; i++)
{
entities[i].print();
entities[i].update();
entities[i].print();
cout << endl << "next ship: " << endl;
}
system("PAUSE");
return 0;
}
好的,所以它编译得很好(stdafx.h 仅在 Visual Studio 中需要)但是我收到一个运行时错误,这是在它试图进入被覆盖的更新函数时在 0xffffffffffffffff 处的访问冲突。在调试信息中,它始终看起来像虚函数指针 (__vfptr) 明显指向其他地方而不是它应该在的地方 (0xcdcdcdcdcdcdcdcd),而且它总是相同的位置,即使在另一个代码中我试图做同样的事情.
目前研究: 原因 #1(不适用):在调用前释放的 DLL 中使用函数 原因#2(再次不适用):程序员忘记继承。 我没有在任何具有相同问题的线程中遇到任何其他问题,并且我已经调试了几天。如果我删除覆盖,它只会调用 Base class 的函数。 有什么线索吗?
您不应使用 malloc
分配 C++ 对象。 new
是正确的运算符。
您将无法实例化 Entity
,因为它是一个抽象 class。
你需要的是指向 Entity
的指针数组,并将它们关联到具体 Entity
(Ship
或 MerchantShip
)的地址,如下所示:
typedef Entity *PEntity;
PEntity entities[2];
entities[0] = new Ship();
entities[1] = new MerchantShip();
当您通过指针调用虚方法时,多态性将正确应用:
for (int i=0; i<2; i++) {
entities[i]->print();
entities[i]->update();
entities[i]->print();
}
真正重要的是要明白这里没有Entity
,只有具体的Entity
。 Entity
只是一个概念; Ship
(或MerchantShip
)是其具体实现之一。您可以通过它们的抽象接口来操作具体对象。
malloc
不创建和初始化对象,只是保留一块内存。在 C++ 中,您应该远离手动分配的动态数组并使用 std::vector
而不是
#include "stdafx.h"
// these headers are discouraged. Use cstdlib and cstdio instead.
//#include <stdlib.h>
//#include <stdio.h>
#include <iostream>
#include <vector>
#include <memory>
using namespace std;
class Entity
{
public:
int x, y;
virtual void update() = 0;
void print()
{
cout << "x:" << x << ", y:" << y << endl;
}
virtual ~Entity() {} // any base-class should have this
};
class Ship: public Entity
{
public:
virtual void update()
{
Move();
}
void Move(){x++;};
};
class MerchantShip: public Ship
{
public:
void update()
{
DontMove();
}
void DontMove(){};
};
int main(int argc, char* argv[])
{
int EntityNumber = 2;
std::vector<std::unique_ptr<Entity>> entities(EntityNumber);
// the array is empty so you have to create some objects in it
entities[0] = new MerchantShip;
entities[1] = new Ship;
for (int i = 0; i < EntityNumber; i++)
{
entities[i].print();
entities[i].update();
entities[i].print();
cout << endl << "next ship: " << endl;
}
system("PAUSE");
return 0;
}
我还在你的基础上添加了一个虚拟析构函数class。