访问冲突。 C ++多态性

时间:2014-01-01 10:42:43

标签: c++ polymorphism

我有点开始学习C ++中的多态性。此代码为我提供了“访问冲突读取位置0xFDFDFD00”。 Visual Studio 2012专业版。调试器说,“i”的“__vfptr”是“0xfdfdfd00 {???}”。

#include <iostream>
#include <vector>

using namespace std;

class Enemy {
public:
    virtual void loop() = 0;
};

class EnemyA{
public:
    void loop() {
        cout << "Pew-pew\n";
    }
};
class EnemyB {
public:
    void loop() {
        cout << "Pow-pow\n";
    }
};
class EnemyC {
public:
    void loop() {
        cout << "KABOOM\n";
    }
};

vector <Enemy*> enemies;

int main() {
    enemies.push_back((Enemy*) new EnemyA());
    enemies.push_back((Enemy*) new EnemyB());
    enemies.push_back((Enemy*) new EnemyC());

    for (Enemy* i : enemies) {
        i->loop();
    }
}

7 个答案:

答案 0 :(得分:1)

要从EnemyA继承Enemy,您需要执行以下操作:

class EnemyA : public Enemy {
  // ...
}

同样适用于EnemyBEnemyC

否则,您将EnemyA*投射到Enemy*,其中EnemyAEnemy是完全不相关的类 - 这不安全。如果您没有将(Enemy*)演员阵容放在那里,那么本来会抓住这个。这是执行reinterpret_cast,只是盲目地让你在不相关的指针之间进行转换。

如果你曾经试图完全没有施放,你会得到这样的错误:

error: no matching member function for call to 'push_back'
    enemies.push_back(new EnemyA());
    ~~~~~~~~^~~~~~~~~

由于从派生指针到基指针的转换是一个隐式转换,这应该有效,所以你可以告诉你实际上没有从EnemyA派生Enemy

我们的教训不仅仅是在那里坚持使用C风格的演员来尝试使代码运作。

答案 1 :(得分:1)

你从未真正继承Enemy。这就是你需要施放所有敌人的原因。

#include <iostream>
#include <vector>

using namespace std;

class Enemy {
public:
    virtual void loop() = 0;
};

class EnemyA : public Enemy {
public:
    virtual void loop() {
        cout << "Pew-pew\n";
    }
};
class EnemyB : public Enemy {
public:
    virtual void loop() {
        cout << "Pow-pow\n";
    }
};
class EnemyC : public Enemy  {
public:
    virtual void loop() {
        cout << "KABOOM\n";
    }
};

vector <Enemy*> enemies;

int main() {
    enemies.push_back(new EnemyA());
    enemies.push_back(new EnemyB());
    enemies.push_back(new EnemyC());

    for (Enemy* i : enemies) {
        i->loop();
    }
}

请注意,您仍然有内存泄漏。您从未删除使用new创建的实例。就在这里,没关系,因为结束这个过程将释放大多数系统上的所有内存,当你编写更大的程序时,你需要注意这一点。

答案 2 :(得分:1)

你忘了真正从Enemy类继承:

class Derivet : public Base {};

答案 3 :(得分:1)

您的课程EnemyAEnemyBEnemyC均未从Enemy继承。

这三个类应该是,

class EnemyA : public Enemy{
public:
    void loop() {
        cout << "Pew-pew\n";
    }
};
class EnemyB : public Enemy {
public:
    void loop() {
        cout << "Pow-pow\n";
    }
};
class EnemyC : public Enemy {
public:
    void loop() {
        cout << "KABOOM\n";
    }
};

答案 4 :(得分:0)

您需要class EnemyA等继承class Enemy

换句话说:

class EnemyA : public Enemy
{
   ... 
};

等等。

答案 5 :(得分:0)

你需要从主类继承 使用

class EnemyA : public Enemy {
public:
    void loop() {
    cout << "Pew-pew\n";
    }
};

答案 6 :(得分:0)

这与多态无关,而是与虚拟类的继承。

为了实现这个目的,你必须让EnemyA通过EnemyC从Enemy继承并移除演员,如下所示:

class EnemyA: public Enemy { // fight the powers that be ?
public:
    void loop() {
        cout << "Pew-pew\n";
    }
};

// ....

enemies.push_back(new EnemyA());

在当前状态下,您的数组仅包含指向虚拟类Enemy的指针,该类仅定义了一个接口,但没有为loop()实现。

演员基本上告诉编译器“让我这样做,我知道我在做什么”所以编译器没有抱怨,但是当代码试图找到一个循环方法来执行时,它只找到一个空表虚拟方法这是导致错误的原因。