C ++多态性中的访问冲突(指向错误位置的虚拟指针函数?)

时间:2015-01-02 12:45:51

标签: c++ inheritance polymorphism access-violation

这变得很奇怪。 Ship继承自Ship的Entity和MerchantShip,其他类型将在以后添加,但基本思想和教授要求的是我使用多态,以便我可以处理主类的集合(指针在我的实现中使用已分配的内存作为数组),因此在后面的所有三个类中都有一个虚拟的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)指向其应该位置的其他位置(0xcdcdcdcdcdcdcdcdcd),它始终是相同的位置,即使在我试图做同样事情的另一个代码中。

到目前为止的研究: 原因#1(不适用):在被调用之前释放的DLL中使用函数 原因#2(再次不适用):程序员忘记继承。 我没有在任何具有相同问题的线程中遇到任何其他问题,并且我已经调试了几天。如果我删除覆盖它将只调用Base类的函数。 有线索吗?

2 个答案:

答案 0 :(得分:4)

您不应该使用malloc来分配C ++对象。 new是正确的运算符。

您将无法实例化Entity,因为它是一个抽象类。

您需要的是一系列指向Entity的指针,并将其与具体EntityShipMerchantShip)的地址相关联,如下所示:

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,只是具体EntityEntity只是一个概念; Ship(或MerchantShip)是其具体实现之一。您可以通过抽象接口操作具体对象。

答案 1 :(得分:1)

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;
}

我还在你的基类中添加了一个虚析构函数。