我不理解Stroustrup的 A Tour of C ++ ,第43和44页的继承示例。我复制了一个表明我困惑的最小例子:
#include <iostream>
class Shape {
public:
virtual void draw() const = 0;
virtual ~Shape() {};
};
class Circle : public Shape {
public:
Circle(int p, int rr) : x{p}, r{rr} {}
void draw() const { std::cout << "In Circle::draw()" << std::endl; }
private:
int x;
int r;
};
class Smiley : public Circle {
public:
Smiley(int p, int r): Circle{p,r}, mouth(nullptr) {}
~Smiley() { delete mouth; }
void draw() const { std::cout << "In Smiley::draw()" << std::endl; }
private:
Shape* mouth;
};
int
main(int argc, char *argv[])
{
Circle *smiley;
smiley = new Smiley(3, 4);
smiley->draw();
Circle *circle;
circle = new Circle(3, 4);
circle->draw();
return 0;
}
令我困惑的是Circle :: draw不是虚拟的。我看到了,并认为这一定是一个错字。由于虚拟表示要查看定义的派生类,因此我不认为Smiley的绘制将从基本Circle引用中以多态方式调用。但是,我运行代码并获得以下输出:
In Smiley::draw()
In Circle::draw()
请帮忙。这怎么可能?当Circle :: draw不是虚拟时,Smiley :: draw是如何从Circle *指针调用的?当heirarchy的基类是虚拟的(Shape :: draw)时,是否没有必要为更多派生类的函数(例如Smiley :: draw)声明派生类函数virtual(例如Circle :: draw)?
答案 0 :(得分:11)
Circle::draw
实际上是虚拟的!这是因为Shape::draw
是虚拟的。从基类覆盖虚函数时,该函数自动为虚函数,不需要关键字。我想提供虚拟关键字,以明确它是一个虚拟功能,但它是可选的。
在C ++ 11中,您可以标记重写的函数override
,以确保它们实际上覆盖了虚函数。这可以防止错误。
void draw() const override
答案 1 :(得分:2)
我认为答案是即使没有指定,绘制仍然是虚拟的,只要第一次绘制声明(在类层次结构的顶部)被声明为虚拟。