鉴于以下代码:
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'
有谁能告诉我为什么编译器没有生成代码,以便它可以在朗姆酒时绑定虚函数?
答案 0 :(得分:2)
您通过指向Base
的指针调用虚拟成员函数。这意味着您只能调用Base
类中存在的方法。您不能简单地将方法动态添加到类型中。
答案 1 :(得分:1)
虽然有点迟了作为答案,直接引用 C ++ Primer 关于如何解决与继承相关的函数调用。 您的代码在名称查找时失败(下面的步骤2),这是静态完成的。
了解如何解决函数调用至关重要 理解C ++中的继承。给出调用p-&gt; mem()(或 obj.mem()),发生以下四个步骤:
首先确定p(或obj)的静态类型。因为我们在打电话 一个成员,该类型必须是类类型。
在类中查找与p(或obj)的静态类型对应的mem。如果找不到mem,请查看直接基类和 继续上课,直到找到mem或最后一堂课 被搜查。如果在课程或其封闭基础中找不到mem 类,然后调用将无法编译。
找到mem后,执行普通类型检查(§6.1,第203页),根据找到的定义查看此调用是否合法。
- 醇>
假设呼叫合法,编译器会生成代码,具体取决于呼叫是否为虚拟:
- 如果mem是虚拟的并且通过引用或者进行调用 指针,然后编译器生成代码以在运行时确定 根据对象的动态类型运行哪个版本。
- 否则,如果该功能是非虚拟的,或者该呼叫是在 对象(不是引用或指针),编译器生成正常 功能调用。