C++继承和方法重载混淆
对不起,这是如此做作,但它涉及到一个作业问题。我明白为什么一切都会发生,除了我评论的那一行。有人可以向我解释为什么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;
}
类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*)
。
纠正我,如果我错了,但我收集的是这样的: 编译器查看指针类型,它是Y1。所以它进入Y1类,并找出哪个f()最匹配。然后使用Y1指向的对象的类型Y2,并调用Y2中与Y1中决定的签名具有相同签名的方法? –
@ user1137940:是的,如果第一步发现了“虚拟”功能,就会发生这种情况。我想这也是我在我的回答中所说的。 –
重载分辨率是根据所涉及的静态类型确定的。
Y1Pointer->f(X2Pointer)
火柴Y1::f(const X1 *x)
,因为静态类型的Y1Pointer
是Y1*
,所以Y1::f(const X1 *x)
是到f
调用使用X2*
参数的最佳匹配。
Y1::f(const X1 *x)
是虚拟的,所以调用的实际功能是由动态类型决定的。 Y1Pointer
指向一个Y2
,因此Y2
版本的f(const X1 *x)
被调用。
Y1
类没有超载消耗X2 *
。函数调用Y1Pointer->f(X2Pointer)
的最佳匹配是Y1::f(X1 const *)
。事实上,Y1Pointer
点比Y1
派生的实际对象无关紧要,因为它与选择的过载无关。
正如其他提到的问题是功能隐藏。但是你可以做的是写在Y1行using Y0::f;
里面以得到你想要的结果。
C++没有做任何事情。它是你这样做的人 –
这几乎是一个最小例子的*相反*。我们不需要演示你*做什么*了解 - 只是你不知道的一个例子。 –