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

时间:2011-11-02 22:55:09

标签: c++

我在虚函数和参考中有一个问题。当我尝试准备面试时,这是一个难题。我谷歌一段时间,但看不到确切的情况。

代码如下:

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。有人能告诉我为什么vtable不会选择B的实现吗?感谢

6 个答案:

答案 0 :(得分:2)

fooB中是虚拟的,因为它会覆盖基类中的虚函数,即使它未显式声明为virtual

通过q->foo()调用的对象的派生类型最多的是CC foo的最终覆盖,其签名为void foo() C::foo 1}}所以这是被调用的函数。

答案 1 :(得分:2)

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

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

答案 2 :(得分:1)

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

答案 3 :(得分:0)

AFAIK:

一旦使用了vtable - 在这种情况下强制virtual A::foo声明 - 你声明的类型并不重要,它总是调用最具体方法的方法 - 在这种情况下是C::foo

答案 4 :(得分:0)

  

有人能告诉我为什么vtable不会选择B的实现吗?

这是拥有虚函数的重点,因此通过基类指针调用overriden方法仍将从派生类调用该方法。

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

即使foo()virtual中的B未标记C,它仍然是虚函数,因为它在A中声明为此类。

如果您希望调用B::foo(),则需要明确调用它。

q->B::foo();

答案 5 :(得分:0)

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

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