我有两个与继承相关的类: -
class Base
{
public:
virtual void f(int x)
{
cout << "BASE::int" << endl;
}
virtual void f(double x)
{
cout << "BASE::double" << endl;
}
};
class Derived : public Base
{
public:
virtual void f(str::string s)
{
cout << "DERIVED::string" << endl;
}
};
我在派生类中使用不同的参数提供了相同的方法。这意味着而不是重写我隐藏了这个函数的基类版本。因此,以下电话预计对我来说很清楚。
std::string str("Hello");
Base b;
b.f(1); //calls base class version.
b.f(str); //error.
Derived d;
d.f(1); //error.
d.f(str); //calls derived class version.
但我无法澄清这最后一种情况。
Base *b = new Derived;
b->f(str); //results in error.
编译器是否会使用vtable和vptrs将此调用绑定到f的派生版本。但相反,它正在做其他事情。任何人都可以提供完整的路径,编译器将如何根据语言机制尝试解析此调用。
答案 0 :(得分:2)
如果您的指针属于Base*
类型,那么您只能&#34;看到&#34;在课程Base
中定义的成员。编译器没有(或假装没有)&#34;知道&#34;该变量确实指向Derived
的实例,即使您刚刚在上一行中为其分配了一个。
当您将变量声明为Base*
类型时,您需要告诉编译器:将其视为可以指向Base
或任何类0}的内容从中衍生出来。因此,您无法访问在特定派生类中定义的成员,因为无法保证指针实际指向该派生类的实例。
答案 1 :(得分:1)
vtable仅在运行时进入图片。生成的程序集将查找函数的vptr值并跳转到该地址。这也意味着多态性受到限制&#34;到Base
知道的函数。请注意,这也是更有意义的 - 类的定义应仅依赖于自身及其父级。如果您想让Base* b
了解Derived
实施的虚拟功能,您最终会得到Base
中vtable条目的数量,具体取决于其子项。