3

很抱歉,这太做作了,但这与家庭作业问题有关。我理解为什么一切都会发生,除了我评论的那一行。有人可以向我解释为什么 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;
}
4

4 回答 4

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函数,被Y2and 覆盖,因此调用Y2::f(const X1*).

于 2012-11-11T15:00:43.173 回答
1

重载解决方案是根据所涉及的静态类型确定的。

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

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

于 2012-11-11T15:04:12.703 回答
1

该类Y1没有消耗X2 *. 函数调用的最佳匹配Y1Pointer->f(X2Pointer)Y1::f(X1 const *). 您所指向的实际对象的Y1Pointer派生程度高于这一Y1事实并不重要,因为它与选择的重载无关。

于 2012-11-11T15:05:09.107 回答
0

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

于 2012-11-11T15:13:13.657 回答