C++继承:派生类的虚方法不被调用[重复]

Posted

技术标签:

【中文标题】C++继承:派生类的虚方法不被调用[重复]【英文标题】:C++ inheritance: the virtual method of the derived class is not called [duplicate] 【发布时间】:2012-08-20 08:32:58 【问题描述】:

可能重复:Store two classes with the same base class in a std::vector

我在 C++ 中遇到了继承问题。这里我写了一个简单的代码来说明我的问题:

//Animal.h
class Animal

public:

Animal();
~Animal();

virtual const void Eat();
;

//Bear.h
class Bear: public Animal

public:

Animal();
~Animal();

virtual const void Eat();
;

//Animal.cpp
const void Animal::Eat() 


//Bear.cpp
const void Animal::Eat() 
 //Do something

现在,在另一个类中,我声明了一个应该包含动物的向量,然后我创建了一个 Bear 并将其推送到我的向量中:

std::vector<Animal> a;
Bear b;
a.push_back(b);

现在的问题是,当我遍历我的动物向量并尝试调用 Eat() 时,会调用基类(动物)的 Eat 方法,而不是 Bear Eat 方法。

即使尝试使用dynamic_cast it 也不起作用:dynamic_cast 失败

dynamic_cast<Bear*>(&a.at(0));

我做错了什么?是因为我缺少拷贝构造函数吗?

【问题讨论】:

看到这个:***.com/questions/8777724/… 【参考方案1】:

您必须创建一个包含动物(智能)指针的向量。

对象向量遭受对象切片

我假设Bear.cpp 中的void Animal::Eat() 是一个错字,否则您的代码将无法编译。

另外,const void?你想确保你不修改任何东西?

【讨论】:

一个有趣的问题是 C++11(向量使用移动语义)是否仍然存在这个问题。实际上,我认为它应该是“神奇地”修复的。毕竟,那时不应该复制任何动物,但熊按原样(可能包括 vtable)? @Damon 甚至没有受到质疑。当您声明 std::vector&lt;Animal&gt; 时,您明确表示您想要 Animal 对象。你将不再拥有熊。 @Damon,试着想想你将如何存储它。 (以及如何实现 operator[])【参考方案2】:

启用多态需要两件事:虚函数和指针。你没有指针。您的 std::vector 必须是 Animal* 的向量(或 C++11 中的 std::unique_ptr),而不是 Animal

std::vector<Animal*> a;
Bear b;
a.push_back(b);
a[0] -> eat();

那么,你的熊函数eat()Animal::。纠正它。

另外,析构函数也必须是虚拟的:析构函数调用也必须是多态的。

【讨论】:

我想过切片问题,但我没想到指针会解决问题。谢谢大家,我学到了一些新东西 但我还是很好奇,当我把熊放入动物载体中会发生什么?它是否调用了基本的复制构造函数并放置了动物而不是熊? @ISTB Bear 是动物(因为继承关系)。因此,如果您将 Bear 放入 Animal(而不是 Animal*)就像使 Animal a = b 其中 b 是 Bear:您可以这样做,但是您在 Animal 中仅复制 Bear 的一些信息(它们共有的成员)。真诚地说,我不知道在这种情况下它是否只被称为 Animal 的构造函数,或者它是否被称为 Bear 的构造函数,然后我们在 Animal 中拥有 Bear 的部分副本,正如我所说的。结果是一样的:你没有 Bear 而是 Animal:所以调用 Animal 的 eat()。 是的,我认为首先调用 Animal 构造函数,然后调用复制构造函数,它当然只复制熊的“动物”信息而不是熊信息

以上是关于C++继承:派生类的虚方法不被调用[重复]的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 继承中,当指向基类的指针对象指向派生类时,不调用派生类析构函数

C++子类如何调父类的虚函数

深入理解C++ 虚函数表

c++ 中如何调用基类的虚函数?

c++中,虚函数能不能被继承

探索c++虚函数表