引用类型转换中的c++虚函数

C++ virtual function in type casting of reference

本文关键字:函数 c++ 类型转换 引用      更新时间:2023-10-16

我对虚函数和引用有一个疑问。这是我准备面试时遇到的一个难题。我在谷歌上搜索了一段时间,但没有看到确切的情况。

代码如下:

class A{
public:
 virtual void foo() {cout << "A::foo" << endl;}
};
class B: public A{
public:
 void foo() {cout << "B::foo" << endl;}
};
class C: public B{
public:
 void foo() {cout << "C::foo" << endl;}
};
int main(void){
 C c;
 B *q;
 q = &c; q->foo();
 return 0;
}

我认为输出将是B::foo,但答案实际上是C::foo。有人能告诉我为什么虚表不选择B的实现吗?由于

如果foo 不是虚指针,则调用的函数将基于指针的类型,并调用B::foo()

由于foo在基类中被定义为虚的,因此它在所有派生类中都保持虚的。在这种情况下,调用的函数是基于指向的对象的类型,而不是指针的类型。由于指向的对象是C,因此调用的函数是C::foo()

fooB中是虚函数,因为它覆盖了基类中的虚函数,即使它没有显式声明为virtual

通过q->foo()调用的对象的最派生类型是C,而Cfoo的最终覆盖(带有void foo()签名)是C::foo,因此这就是被调用的函数

因为q指向一个C对象,并且它的虚函数表包含一个虚函数foo。记住,在类中声明的任何虚函数在任何派生类中都是虚的。这是使用基类来访问派生类的方法。

韩文:

一旦使用了虚表——在这种情况下是由A::foovirtual声明强制的——声明什么类型并不重要,它总是调用最特定的方法的方法——在这种情况下是C::foo

谁能告诉我为什么虚表不选择B的实现?

这就是使用虚函数的全部意义所在,因此通过基类指针调用被重写的方法仍然会从派生类调用该方法。

qB *类型的,但是它指向一个C对象。因此,当您调用虚函数foo()时,将调用C::foo()实现。

尽管foo()BC中没有标记为virtual,但它仍然是一个虚函数,因为它在A中是这样声明的。

如果你想要调用B::foo(),你需要显式地调用它。

q->B::foo();

foo()是虚函数,这意味着调用q实际指向的实例的类中定义的版本,而不是指针类型中类中定义的版本。

请记住,一旦成员函数在类层次结构的某个地方被标记为虚函数,它就是虚函数,也就是说,不需要在类B和C中再次显式地将函数标记为虚函数,因为在类a中已经这样做了。