这是类定义:
class Shape { public:
virtual void draw() = 0; ...
};
class Circle : public Shape {
public:
void draw() { ... }
... };
class Rectangle : public Shape { public:
void draw() { ... } ...
};
class Square : public Rectangle {
public:
void draw() { ... }
... };
这是客户端代码:
Square* sq = new Square;
Rectangle* rect = new Rectangle;
Shape* ptr_shape;
ptr_shape = sq;
ptr_shape->draw();
rect->draw();
我正在阅读的一本书说最后一个陈述是静态绑定:
然而,该语句仍然看起来是动态绑定给我的,因为rect->draw
应该被" vtable"中的指针调用。在运行时间rect
。
有没有人对rect->draw
是静态绑定还是动态绑定有想法?
答案 0 :(得分:8)
Rect::draw()
不是final
而rect
是指针,因此它使用动态绑定。
但是如果所有变量都在本地范围内且所有类型都已知,编译器可以使用去虚拟化作为优化。
答案 1 :(得分:1)
您对vtable的整体理解是正确的。
我认为这本书试图说的是编译器可能并且通常会优化rect-> draw,而无需转到vtable。
在这种情况下,编译器可以看到rect指向Rectangle对象。
在大多数生产代码中,很少会出现这种情况。
答案 2 :(得分:0)
这取决于哪里。在类的代码之外,这将始终是动态绑定。在对象构造期间(在继承链中的任何构造函数内部),虚拟表查找被暂停,因为子类对象可能尚未初始化。