我有点开始学习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();
}
}
答案 0 :(得分:1)
要从EnemyA
继承Enemy
,您需要执行以下操作:
class EnemyA : public Enemy {
// ...
}
同样适用于EnemyB
和EnemyC
。
否则,您将EnemyA*
投射到Enemy*
,其中EnemyA
和Enemy
是完全不相关的类 - 这不安全。如果您没有将(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)
您的课程EnemyA
,EnemyB
或EnemyC
均未从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()实现。
演员基本上告诉编译器“让我这样做,我知道我在做什么”所以编译器没有抱怨,但是当代码试图找到一个循环方法来执行时,它只找到一个空表虚拟方法这是导致错误的原因。