试图了解动态绑定和虚函数

时间:2014-01-23 22:36:26

标签: c++ inheritance polymorphism virtual-functions dynamic-binding

鉴于以下代码:

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...

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

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

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

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

虽然有点迟了作为答案,直接引用 C ++ Primer 关于如何解决与继承相关的函数调用。 您的代码在名称查找时失败(下面的步骤2),这是静态完成的。

  

了解如何解决函数调用至关重要   理解C ++中的继承。给出调用p-&gt; mem()(或   obj.mem()),发生以下四个步骤:

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

  2.   
  3. 在类中查找与p(或obj)的静态类型对应的mem。如果找不到mem,请查看直接基类和   继续上课,直到找到mem或最后一堂课   被搜查。如果在课程或其封闭基础中找不到mem   类,然后调用将无法编译。

  4.   
  5. 找到mem后,执行普通类型检查(§6.1,第203页),根据找到的定义查看此调用是否合法。

  6.   
  7. 假设呼叫合法,编译器会生成代码,具体取决于呼叫是否为虚拟:

         

    - 如果mem是虚拟的并且通过引用或者进行调用   指针,然后编译器生成代码以在运行时确定   根据对象的动态类型运行哪个版本。

         

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

  8.