为什么程序会这样写输出? 我想知道为什么这个C++程序的输出是: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; }

为什么程序会这样写输出? 我想知道为什么这个C++程序的输出是: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; },c++,function,inheritance,C++,Function,Inheritance,以及如何更改f函数体以及在输出中获得Y:f1所需的参数?您会遇到这个问题,因为函数未声明为虚拟函数。您需要将虚拟限定符添加到X的f1以允许子类重写它 class X { public: virtual void f1() { cout<<"X:f1"<<endl;} }; class Y : public X { public: virtual void f1() { cout<<"Y:f1"<<endl;} }; 出现此问题是

以及如何更改f函数体以及在输出中获得Y:f1所需的参数?

您会遇到这个问题,因为函数未声明为虚拟函数。您需要将虚拟限定符添加到X的f1以允许子类重写它

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

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

出现此问题是因为函数未声明为虚拟。您需要将虚拟限定符添加到X的f1以允许子类重写它

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

class Y : public X {
public:
    virtual void f1() { cout<<"Y:f1"<<endl;}
};
由于X::f1不是虚拟的,因此对它的调用是静态调度的,即在本例中,它们是基于X的静态类型(即X)而不是动态类型(即Y)进行调度的

换句话说,因为X::f1不是虚拟的,所以在调用fy时X指向Y的一个实例这一事实没有被考虑在内——编译器将所有对X::f1的调用分派到X的f1,而不管X指向的对象的动态类型,即运行时类型

<>与其他语言不同,例如java,C++中的成员函数默认不是虚的——必须显式指定要子类能够重写它们。

要获得预期的输出,您需要向X::f1添加一个虚拟限定符-您不能像您建议的那样通过更改f的主体来明智地实现您想要的结果,因为您正在丢弃关于X的动态类型的信息,但是在这种情况下,您可以更改f的参数以接受Y*而不是X*。

因为X::f1不是虚拟的,所以对它的调用是静态调度的,也就是说,在这种情况下,它们是基于X的静态类型(X)而不是动态类型(在这种情况下是Y)进行调度的

换句话说,因为X::f1不是虚拟的,所以在调用fy时X指向Y的一个实例这一事实没有被考虑在内——编译器将所有对X::f1的调用分派到X的f1,而不管X指向的对象的动态类型,即运行时类型

<>与其他语言不同,例如java,C++中的成员函数默认不是虚的——必须显式指定要子类能够重写它们。


要获得预期的输出,您需要向X::f1添加一个虚拟限定符-您不能像您建议的那样通过更改f的主体来明智地实现您想要的结果,因为您正在丢弃关于X的动态类型的信息,但在这种情况下,您可以将f的参数更改为接受Y*而不是X*。

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

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

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

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

以及如何更改f函数体和获取 Y:f1在输出端

你的问题的实际答案是:

void f(Y* y) { y -> f1(); }
尽管在派生类中使用具有相同名称和签名的非虚方法并没有多大意义,只是产生了难以捕获的问题

以及如何更改f函数体和获取 Y:f1在输出端

你的问题的实际答案是:

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

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

将函数f1声明为虚拟如果您来自Java、Python等语言,其中所有实例方法都是虚拟的,然后你应该了解它们。将函数f1声明为virtual如果你来自Java、Python等语言,其中所有实例方法都是虚拟的,那么你应该了解它们。是的,你是对的。非常感谢,我只是忘记了那个“微小”的细节:干杯@AICICN当然不是一个小细节,但C++编程中的一个非常基础的问题!这真的是问题的答案吗?@Slava:我补充了一点来更明确地回答它。@StuartGolodetz我明白,但他的问题很具体-如何更改函数fYeah,你是对的。非常感谢,我只是忘记了那个“微小”的细节:干杯@AICICN当然不是一个小细节,但C++编程中的一个非常基础的问题!这真的是问题的答案吗?@Slava:我添加了一点来更明确地回答它。@StuartGolodetz我理解,但他的问题是具体的-如何更改函数F感谢回答:这不是我发布的代码。你在上面的帖子中插入了我没有的虚拟内容。@omar khaled下次在第一枪时做得更好!这不是我发布的代码。你在上面的帖子中插入了我没有的虚拟内容。@omar khaled下次在第一枪时做得更好!