【问题标题】:Dynamic method binding动态方法绑定
【发布时间】:2015-06-30 13:48:09
【问题描述】:
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() { . . . }
. . .
};


Rectangle* rect = new Rectangle;

rect->draw(); // Statically bound to the draw in the Rectangle class

在一本教科书中,“编程语言的概念,第 10 章”,

有一部分是关于动态方法绑定的。

我认为 rect 指向的对象的类型无法静态解析,因为 rect 是多态引用类型。 rect 也可能在运行时引用 Sqaure 类型的对象。

代码上面最后一行不正确??

【问题讨论】:

  • 我修好了,有错误
  • 一个足够聪明的优化器可能能够证明rect在这个例子中总是指向Rectangle的一个实例,并静态绑定到Rectangle::draw。无论哪种方式,可观察到的效果都是相同的,所以不清楚你为什么会关心。

标签: c++ dynamic-binding


【解决方案1】:

考虑以下示例

int main
{
    Shape* cir = new Circle;
    Shape* rec = new Rectangle;
    Shape* sqr = new Square;

    cir->draw();    // Circle::draw
    rec->draw();    // Rectangle::draw
    sqr->draw();    // Square::draw
}

所有这些变量cirrecsqr 都是Shape*,但由于多态性,它们将调用各自的draw 方法。当我们重复使用相同的变量时,这一点更加清楚

int main
{
    Shape* shape = new Circle;
    shape->draw();  // Circle::draw
    delete shape;

    shape = new Rectangle;
    shape->draw();  // Rectangle::draw
    delete shape;

    shape = new Square;
    shape->draw();  // Square::draw
    delete shape;
}

在这种情况下,draw 函数必须在运行时解析,因为shape 的底层类型可以在整个运行时修改。

【讨论】:

    【解决方案2】:

    从概念上讲,因为 draw() 是一个虚方法,rect->draw() 将始终参考由rect 指向的Rectangle 派生对象的vtable

    然而

    如果编译器可以证明rect 实际上指向的是Rectangle 的实例,而不是从它派生的覆盖draw() 方法的其他类,那么它是允许的(但不是必需的) 绕过多态查找,从而节省了一些内存提取。

    【讨论】:

      【解决方案3】:

      你的代码没有问题,对于多态类virtual的函数调用是在运行时使用虚函数表解决的,实际上在c++中称为动态绑定。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-04-02
        • 2023-04-05
        • 1970-01-01
        • 1970-01-01
        • 2018-10-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多