class base
{
public:
virtual void showbase() {
// ----------
}
};
class base1 {
public:
virtual void showbase1() {
// -------
}
};
class derived : public base, public base1
{
void showbase() {
// ----
}
void showbase1() {
// -------
}
};
int main()
{
base* p = new derived();
p->showbase1();
base1* p1 = new derived();
p1->showbase();
}
根据我对虚函数的理解,编译器会将它与运行时(vtable机制)一起处理,那么为什么我会收到编译时错误。
答案 0 :(得分:2)
要模拟编译器,请考虑编译器看到的内容:
class base
{
public:
virtual void showbase() {
// ----------
}
};
base* p = /*blah blah*/;
p->showbase1();
是的,base
是一个多态类。而p
确实是指向base
的指针。但由于p
仅指向base
,而且重要的是 指向base1
(其中showbase1
存在),编译器会将上述代码解释为这个。显然,我在解读:
Here is a class named `base` with a single virtual method called `showbase`. Here is a pointer to a `base` object. Call the method named `showbase1`
编译器抱怨:
嗯,对不起伙计,但base
没有一个叫做的方法showbase1
。
你问:
[我]关于虚函数的理解是编译器处理的 它在运行时。为什么我得到编译时错误?
因为你写的代码是无稽之谈。这里基本上是多态的工作原理。
但你要做的是:
答案 1 :(得分:1)
您的基类只知道自己的成员函数,因此您不能以这种方式使用它。你可以这样做:
base* p = new derived();
p->showbase();
base1* p1 = new derived();
p1->showbase1();
要回答关于运行时多态性的问题,正如你所说,它正在通过vtable处理运行时多态(后期绑定)。但是对于多重继承,每个基类基本上都有一个vtable。您无法通过指向另一个基类的指针访问一个基类'vtable。
答案 2 :(得分:1)
指向派生类的基类指针只能访问基类中定义的成员函数。通过它尝试访问派生类中定义的其他函数是非法的。在您的情况下,base
类未定义showbase1
,因此这是非法的
base* p = new derived();
p->showbase1(); //illegal
但是,你可以这样做:
p->showbase(); // legal because showbase is a member function of base
同样,您无法使用showbase1
类指针访问base
base1* p1 = new derived();
p1->showbase(); //illegal
p1->showbase1(); //legal
答案 3 :(得分:1)
根据我对虚函数的理解,编译器会将它与运行时(vtable机制)一起处理,那么为什么我会收到编译时错误。
“处理它”非常模糊,而且vtables并不神奇;在C ++中,虚拟调度允许调用的实际函数覆盖静态声明的虚函数。这意味着必须在编译时知道被覆盖的函数。
vtable不包含在运行时查找函数所需的信息。相反,它基本上只是一个指向重写函数的指针列表。基础提供了其虚函数的完整列表,因此,给定特定的基类型,编译器在编译时知道在特定函数覆盖的基础的vtable中的位置;编译器可以生成直接到vtable中的那个点的代码,获取指针,并调用覆盖函数。
然后,在运行时,当创建派生类型的实际对象时,派生对象的构造函数填充基础的vtable,以便检查vtable的任何内容都将获得指向派生类型函数的指针。
因此,代码的问题在于,您正在调用的函数showbase()
不在编译器知道您正在访问的类型的虚函数列表中,base1
;编译器无法知道base1's
vtable中的哪个位置获取名为showbase()
的函数覆盖的指针,因为base1
的vtable中没有这样的条目。
答案 4 :(得分:0)
p '静态类型的类型是 base ,因此您只能调用已定义为 base的函数即使最后,也会调用来自派生的函数,因为p的动态类型是派生的
p1也是如此。
也许您的意思是p->showbase();
和p1->showbase1();