试图了解动态绑定和虚拟功能

Trying to understand dynamic binding and virtual functions

本文关键字:虚拟 功能 动态绑定 了解      更新时间:2023-10-16

给定以下代码:

class Base
{
public:    
    virtual void f()
    {
        std::cout << "virtual Base::f()n";
    }
};
class D1 : public Base
{
public:
    virtual void f()
    {
        std::cout << "virtual D1::f()n";
    }
};
int main()
{
    D1 d1;
    Base *bp = &d1;
    bp->f();
    return 0;
}

输出正是我所期望的:

virtual D1::f()
Press <RETURN> to close this window...

但是,一旦我从class Base删除了virtual void f(),编译器就抱怨说:

error: 'class Base' has no member named 'f'

谁能告诉我为什么编译器没有生成代码以使其可以在朗姆酒时绑定虚拟函数?

您正在通过Base指针调用虚拟成员函数。这意味着您只能调用Base类中存在的方法。您不能简单地将方法添加到动态的类型中。

虽然答案很晚,但直接引用了 c 引物 如何解决与继承有关的函数调用。您的代码在名称查找(下面的步骤2)上失败,这是静态完成的。

了解如何解决函数调用对 了解C 的继承。给定调用p-> mem()(或 obj.mem()),以下四个步骤发生:

  1. 首先确定P(或OBJ)的静态类型。因为我们在打电话 成员,该类型必须是类型。

  2. 在类中寻找对应于p(或obj)的静态类型的MEM。如果找不到MEM,请在直接基类中查看 继续上课链,直到找到MEM或最后一堂课 被搜索。如果在班级或其封闭基础中找不到MEM 上课,然后呼叫不会编译。

  3. 找到MEM后,请进行正常类型检查(第6.1节,第203页),以查看此调用是否合法,鉴于找到的定义。

  4. 假设呼叫是合法的,则编译器会生成代码,该代码取决于呼叫是否虚拟:

    - 如果MEM是虚拟的,并且该呼叫是通过参考或 指针,然后编译器生成代码以在运行时确定 基于对象的动态类型运行的哪个版本。

    - 否则,如果该功能是非虚拟的,或者呼叫在 对象(不是参考或指针),编译器会生成普通的 功能调用。

只需使用此主要功能:

int main()
{
    D1 d1;
    D1 *bp = &d1;
    bp->f();
    return 0;
}

这是因为如果bpBase Poiter, name lookup 将从类Base

开始