为什么程序会像这样写输出?

时间:2014-09-03 22:35:45

标签: c++ function inheritance

我想知道为什么这个c ++程序的输出X:f1?是否有y对象的调用,调用Y的f1()是否合乎逻辑?难道不存在遗产吗?我很困惑......

    class X {
    public:
        void f1() { cout<<"X:f1"<<endl;}
    };
    class Y : public X {
    public:
        void f1() { cout<<"Y:f1"<<endl;}
    };
    Y* y = new Y();
    void f(X* x) { x -> f1(); }
    int main () { f (y);
    system("pause");
    return 1;
    }

如何更改f()函数的主体和在输出中获取Y:f1所需的参数?

4 个答案:

答案 0 :(得分:7)

由于X::f1不是virtual,因此会静态调度对它的调用,即在这种情况下,它们会根据x的静态类型(X进行调度。 1}})而不是动态类型(在这种情况下是Y)。

换句话说,因为X::f1不是virtualx在您致电Y时指向f(y)的实例这一事实没有考虑 - 无论对象的动态(即运行时)类型如何,编译器都会将对X::f1的所有调用都调度到X&#39; f1x指出。

与其他语言(例如Java)不同,默认情况下,C ++中的成员函数不是virtual - 您必须明确指定您希望子类能够覆盖它们。

要获得您期望的输出,您需要向virtual添加X::f1限定符 - 您只需更改f的正文即可明智地达到您想要的效果如您所建议,因为您放弃了有关x动态类型的信息,但您可以更改f的参数以接受Y*而不是X* {1}}在这种特殊情况下。

答案 1 :(得分:4)

您遇到此问题,因为该功能未声明为虚拟。您需要将virtual限定符添加到X&#39; f1,以允许子类覆盖它。

class X {
public:
    virtual void f1() { cout<<"X:f1"<<endl;}
};

class Y : public X {
public:
    virtual void f1() { cout<<"Y:f1"<<endl;}
};

如果您不这样做,只有在编译器知道对象的类型时才会调用Y&#39; f1。将其转换为X*时不是这种情况。这是您观察到的行为:

Y* y = new Y;
y->f1(); // prints "Y:f1"
X* x = y;
x->f1(); // prints "X:f1"!

答案 2 :(得分:1)

  

如何更改f()函数的主体和获取的参数   Y:输出处的f1?

您问题的实际答案是:

void f(Y* y) { y -> f1(); }

虽然没有太多意义,在派生类中使用相同名称和签名的非虚方法,除了产生难以捕获的问题。

答案 3 :(得分:0)

我以这种方式在我的编译器中尝试了你的代码

#include<iostream>
using namespace std;
class X {
public:
     virtual void f1() { cout<<"X:f1"<<endl;}
  // ^^^^^^^ Note my changes here!
};
class Y : public X {
public:
    void f1() { cout<<"Y:f1"<<endl;}
};

Y* y = new Y();
void f(X* x) { x -> f1(); }

int main () {
    f(y);
    return 1 ;
}

,输出为Y:F1而非X:F1,因为你说再试一次,