为什么程序会这样写输出

Why does the program writes output like this?

本文关键字:输出 程序 为什么      更新时间:2023-10-16

我想知道为什么这个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所需的参数?

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

换句话说,因为X::f1不是virtual,所以在调用f(y)x指向Y的实例这一事实没有被考虑在内——编译器将所有对X::f1的调用都分派给Xf1,而不管x指向的对象的动态(即运行时)类型如何。

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

为了获得您期望的输出,您需要向X::f1添加一个virtual限定符-您不能按照建议只更改f的主体来合理地实现您想要的内容,因为您正在丢弃有关x的动态类型的信息,但在这种特殊情况下,您可以更改f的参数以接受Y*而不是X*

您会遇到这个问题,因为函数没有声明为虚拟函数。您需要将virtual限定符添加到Xf1中,以允许子类覆盖它

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

如果不这样做,则只有当编译器知道对象的类型时,才会调用Yf1。当您将其转换为X*时,情况并非如此。这就是你观察到的行为:

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

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

您问题的实际答案是:

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

尽管在派生类中使用具有相同名称和签名的非虚拟方法并没有多大意义,但会产生难以捕捉的问题。

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

#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,正如你所说的,再试一次,