为什么程序会这样写输出
Why does the program writes output like this?
我想知道为什么这个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
的调用都分派给X
的f1
,而不管x
指向的对象的动态(即运行时)类型如何。
与其他语言(如Java)不同,C++中的成员函数默认情况下不是virtual
——您必须明确指定您希望子类能够覆盖它们。
为了获得您期望的输出,您需要向X::f1
添加一个virtual
限定符-您不能按照建议只更改f
的主体来合理地实现您想要的内容,因为您正在丢弃有关x
的动态类型的信息,但在这种特殊情况下,您可以更改f
的参数以接受Y*
而不是X*
。
您会遇到这个问题,因为函数没有声明为虚拟函数。您需要将virtual
限定符添加到X
的f1
中,以允许子类覆盖它
class X {
public:
virtual void f1() { cout<<"X:f1"<<endl;}
};
class Y : public X {
public:
virtual void f1() { cout<<"Y:f1"<<endl;}
};
如果不这样做,则只有当编译器知道对象的类型时,才会调用Y
的f1
。当您将其转换为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
,正如你所说的,再试一次,
相关文章:
- 如何将c++程序的一些输出传递给shell,以便在shell中使用
- 使用C++程序合并排序没有得到正确的输出
- 显示错误输出的简单数组排序程序
- 更改.cpp程序的输入文件中数据的位置会意外更改输出
- 如何从Windows应用程序输出到标准?
- 我写了一个C++程序来模拟Enigma机器.我没有得到输出
- 如何使用C++读取另一个程序中的源代码输出
- 为什么我的C++程序的程序集输出充满了 .ascii,没有汇编代码?
- 为什么这个程序的输出不如预期
- 在由Sublime文本3编译后在cmd上显示Java程序输出
- C++ 每次运行程序时我都会"nan"输出的问题
- 如何从 Win32 C++ 应用程序输出到父控制台窗口?
- 这是使用回溯的 nqueen 问题,但我使用了动态 2d 数组,我的程序编译良好,但不返回任何输出
- 而循环:简单的除法程序输出零,不明白为什么
- 如何在 html 页面中插入 cgi 应用程序的输出?
- C 中的输出程序无明显的原因是白色的
- C++:更改简单输出程序的字体
- C++ 简单的输入/输出程序 + 枚举器
- C++字母等效数字代码输出程序
- 编译输出程序集