2012-11-11 134 views
3

对不起,这是如此做作,但它涉及到一个作业问题。我明白为什么一切都会发生,除了我评论的那一行。有人可以向我解释为什么C++正在做它正在做的事情吗?C++继承和方法重载混淆

感谢

#include <iostream> 

using namespace std; 

class X0 {}; 
class X1: public X0 {}; 
class X2: public X1 {}; 

class Y1 
{ 
public: 
    virtual void f(int v)  { cout << "Y1(int)" << endl; } 
    virtual void f(const X0 *x) { cout << "Y1(X0)" << endl; } 
    virtual void f(const X1 *x) { cout << "Y1(X1)" << endl; } 
}; 

class Y2: public Y1 
{ 
public: 
    virtual void f(const X0 *x) { cout << "Y2(X0)" << endl; } 
    virtual void f(const X1 *x) { cout << "Y2(X1)" << endl; } 
    virtual void f(const X2 *x) { cout << "Y2(X2)" << endl; } 
}; 

int main(int argc, char * argv[]) 
{ 
    X2 x2; X2 *X2Pointer = &x2; 
    Y2 y2; Y1 *Y1Pointer = &y2; 

    cout << "What is about to happen?" << endl; 
    //Y1 pointer points to a Y2 object. 
    //The Y2 class, upon being given an X2 pointer, should print Y2(X2) 
    Y1Pointer->f(X2Pointer); 
    cout << "Why did I just print Y2(X1)" << endl; 
    return 0; 
} 
+1

C++没有做任何事情。它是你这样做的人 –

+1

这几乎是一个最小例子的*相反*。我们不需要演示你*做什么*了解 - 只是你不知道的一个例子。 –

回答

3

Y1公开这些存在的f()超载:

class Y1: public Y0 { 
public: 
    virtual void f(int v)  { cout << "Y1(int)" << endl; } 
    virtual void f(const X0 *x) { cout << "Y1(X0)" << endl; } 
    virtual void f(const X1 *x) { cout << "Y1(X1)" << endl; } 
    // ... 
}; 

其他所有方法称为f()Y0继承是隐藏的。也就是说,当你调用

Y1Pointer->f(X2Pointer); 

的编译器上的f()的三个重载过载的分辨率和得出的结论是f(const X1*)是最好的搭配并调用此函数。事实证明,这是一个virtual函数,被Y2覆盖,因此它调用Y2::f(const X1*)

+0

纠正我,如果我错了,但我收集的是这样的: 编译器查看指针类型,它是Y1。所以它进入Y1类,并找出哪个f()最匹配。然后使用Y1指向的对象的类型Y2,并调用Y2中与Y1中决定的签名具有相同签名的方法? –

+0

@ user1137940:是的,如果第一步发现了“虚拟”功能,就会发生这种情况。我想这也是我在我的回答中所说的。 –

1

重载分辨率是根据所涉及的静态类型确定的。

Y1Pointer->f(X2Pointer)火柴Y1::f(const X1 *x),因为静态类型的Y1PointerY1*,所以Y1::f(const X1 *x)是到f调用使用X2*参数的最佳匹配。

Y1::f(const X1 *x)是虚拟的,所以调用的实际功能是由动态类型决定的。 Y1Pointer指向一个Y2,因此Y2版本的f(const X1 *x)被调用。

1

Y1类没有超载消耗X2 *。函数调用Y1Pointer->f(X2Pointer)的最佳匹配是Y1::f(X1 const *)。事实上,Y1Pointer点比Y1派生的实际对象无关紧要,因为它与选择的过载无关。

0

正如其他提到的问题是功能隐藏。但是你可以做的是写在Y1行using Y0::f;里面以得到你想要的结果。