2011-11-02 75 views
0

我在虚函数和引用中有一个问题。当我尝试准备面试时,这是一个难题。我谷歌一段时间,但不能看到确切的情况。参考类型转换中的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的实现吗?由于

+1

'q'指向'C'的一个实例,所以这就是被调用的'foo'的版本。你可以用你的理由更新你的问题*为什么*你认为输出是'B :: foo'? – Ayjay

+0

对不起,我应该提到这是在C++中的文章 – wilson100

回答

0

据我所知:

一旦虚函数表的使用 - 这是在这种情况下,由virtual声明A::foo强制 - 这是你声明什么类型并不重要,它会随时调用最具体方法的方法 - 这在这种情况下是C::foo

2

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

最派生类型通过q->foo()称为对象的是CC的用于foo与签名void foo()最终超控器是C::foo所以这是被调用的函数。

1

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

0

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

这就是虚拟函数的重点,所以通过基类指针调用overriden方法仍然会调用派生类中的方法。

q类型为B *,但它指向一个C对象。所以,当你调用虚函数foo()时,调用C::foo()实现。

即使foo()没有标记virtualBC,它仍然是一个虚函数,因为它是在A宣布为。

如果你想B::foo()被调用,你需要明确地调用它。

q->B::foo(); 
2

foo如果被虚拟的,则称为将基于指针的类型的功能,和B::foo()将被调用。

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

0

foo()是一个虚拟函数,这意味着,在其实例是实际上指向q叫做而不是在指针的类型在该类中定义的一个类定义的版本。

请记住,一旦它被标记为虚拟的地方了类层次结构,即一个需要没有明确标记功能在B级和C再虚拟,因为这已经在A级做了成员函数是虚拟的