在我的一个项目中,我遇到了这个问题,多态性似乎不起作用。派生类似乎不会覆盖基类,但也没有错误。
这是对代码的简化,但它会产生相同的问题。vector
和unique_ptr
的用法与我的项目中相同,我怀疑我对它们的使用是导致问题的原因。
我期待
void print() override
{
printf("B HEJ");
}
覆盖
virtual void print()
{
printf("A HEJ");
}
,但事实并非如此。为什么?
以下是完整的源代码:
#include <iostream>
#include <string>
#include <memory>
#include <vector>
class A
{
public:
virtual void print()
{
printf("A HEJ");
}
};
class B : public A
{
public:
void print() override { printf("B HEJ"); }
};
int main()
{
std::vector<std::unique_ptr<A>> ass;
ass.emplace_back(std::make_unique<A>(B()));
ass[0]->print();
std::cin.get();
}
这里有一个错误:
ass.emplace_back(std::make_unique<A>(B()));
这条线创建一个指向A
的唯一指针,通过从默认构造的B
复制来初始化它。它等同于裸指针的new A(B())
。
您需要创建一个指向B
的唯一指针,因此您的代码应如下所示:
ass.emplace_back(std::make_unique<B>());
在它上面时,不要忘记将虚拟析构函数添加到A
.
您需要make_unique<B>
并将virtual
析构函数添加到基类中。
make_unique<B>
创建一个unique_ptr<B>
,如果B
派生自A
将被unqiue_ptr<A>
接受(移入)。make_unique<A>(B())
复制从B
构造一个A
,对B
进行切片(只会复制默认构造B
的A
部分)。- 只要保留
virtual
方法链,就会调用派生最多的方法。没有virtual
析构函数可确保在具有基类指针vector
时仅调用基类析构函数。结果往往是灾难性的。您希望调用大多数派生类的析构函数 - 因此将基类析构函数virtual
。
#include <iostream>
#include <string>
#include <memory>
#include <vector>
class A
{
public:
virtual ~A() = default;
virtual void print()
{
printf("A HEJ");
}
};
class B : public A
{
public:
void print() override { printf("B HEJ"); }
};
int main()
{
std::vector<std::unique_ptr<A>> ass;
ass.emplace_back(std::make_unique<B>());
ass[0]->print();
}