当我运行下面的代码时。
#include <iostream>
class Shape{
public:
};
class Square:public Shape
{
public:
};
class Circle:public Shape
{
double r;
public:
void SetRadious(double r)
{
std::cout << "R value:" << this->r <<std::endl;
this->r=r;
}
};
int main() {
Shape * s = new Square();
Circle* c= dynamic_cast<Circle*>(s);
c->SetRadious(3.0);
return 0;
}
我得到一个错误信息说:
'Shape' is not polymorphic(形状)。
我看了一下,发现我需要写一些虚拟函数,但是有2个问题。
1) 为什么要这样做,要求一个虚拟函数是没有意义的。
2) 在这种情况下,很多人说我需要虚拟的d'tor,但为什么默认的d'tor不会完全好,默认的d'tor和默认的d'tor有什么区别?
1) 为什么要这样做
因为语言是这样说的。之所以这么说,是因为这种限制可以让程序更快。
要求一个虚拟函数是没有意义的。
对我来说,这很有意义。除非你有一个虚拟函数,否则我认为没有理由使用动态投射。坦率地说,即使是多态类,动态投射也很少有用。
2)在这种情况下,很多人说我需要虚拟d'tor,但为什么默认的不会完全好。
因为默认的不会是虚拟的。
你的例子泄露了内存。如果你试图通过以下操作来修复泄漏的内存 delete s;
,那么程序的行为就会因为缺乏虚拟析构器而无法定义。
像你现在这样的类的层次结构不是 多态 开箱即用。
而 dynamic_cast
要求层次结构是多态的。
使层次结构成为多态的最简单的方法是使基类的析构器成为 virtual
:
class Shape {
public:
virtual ~Shape() = default;
};
这也有一个好处,就是你现在可以安全地打电话给 delete
的指针上 Shape*
其中动态类型是子类之一。
这背后的原因是多态性引入了可能不需要的运行时费用。这也意味着你的类失去了一些类似于C的特性,比如被称为 琐碎 类型。
请注意,一旦你引入了这个虚拟的析构器,那么 c
在
Circle* c = dynamic_cast<Circle*>(s);
将是 nullptr
的行为,以及 c->SetRadius(3.0);
未定义。