作者所说的不良结果是什么
What are the undesirable results the author is talking about?
这个例子取自Bruce Eckel的"C++中的思考"第14章"Upcasting and the Copy Constructor"一节。
#include <iostream>
using namespace std;
class Parent
{
int i;
public:
Parent(int ii) : i(ii) { cout << "Parent(int ii)n"; }
Parent(const Parent& b) : i(b.i) { cout << "Parent(const Parent&)n"; }
Parent() : i(0) { cout << "Parent()n"; }
friend ostream& operator<<(ostream& os, const Parent& b)
{ return os << "Parent: " << b.i << endl; }
};
class Member
{
int i;
public:
Member(int ii) : i(ii) { cout << "Member(int ii)n"; }
Member(const Member& m) : i(m.i) { cout << "Member(const Member&)n"; }
friend ostream& operator<<(ostream& os, const Member& m)
{ return os << "Member: " << m.i << endl; }
};
class Child : public Parent
{
int i;
Member m;
public:
Child(int ii) : Parent(ii), i(ii), m(ii) { cout << "Child(int ii)n"; }
friend ostream& operator<<(ostream& os, const Child& c)
{ return os << (Parent&)c << c.m << "Child: " << c.i << endl; }
};
int main() {
Child c(2);
cout << "calling copy-constructor: " << endl;
Child c2 = c;
cout << "values in c2:n" << c2;
}
作者对此代码作出以下评论:
"Child的运算符<<很有趣,因为它呼叫运营商<lt;对于其中的父零件:通过铸造父对象的子对象&(如果改为转换为基类对象你通常会得到不理想的结果):
return os << (Parent&)c << c.m << "Child: " << c.i << endl;
我还运行了这个程序,将上面的指令替换为:
return os << (Parent)c << c.m << "Child: " << c.i << endl;
推进器运行时没有问题,只有一个预期的差异。现在再次调用Parent
复制构造函数,将参数c
复制到Parent::operator<<()
。
那么,作者所说的不良结果是什么呢?
问题是,当您将Child硬强制转换为Parent(而不是Parent&)时,您只会将使Child成为Child的所有内容都分割掉。
通常,当您的类具有虚拟函数(通常在类层次结构内)时,您可以并且将(取决于内部布局、继承类的数量等)修改vptr,然后一直向下进入未定义行为的领域。也就是说,在类层次结构中不使用引用(或指针)有效地扼杀了所有神奇的继承机制(也称为多态性)。
这有点像在说dog=平面;-通过使用重新解释强制转换(这就是C风格的强制转换),你可以利用编译器发出的任何警告,因为你是在告诉它闭嘴。
一点切线。。。
经验法则:基类不应该是可复制的,而应该是可克隆的。
实现:禁用Copy Constructor和Copy Assignment Operator,或者(简单地)创建一个纯虚拟方法。
松弛:在没有纯虚拟方法的情况下,使基类复制构造函数和赋值运算符protected
更容易警告:这意味着子类现在可以调用其父类的副本,这可能会触发切片问题。
注意:对于C++11,这也适用于移动对应项。
- Fmod 函数清楚地输出一个预期的双精度值,但 if(fmod == 预期的双精度值)的计算结果不是 true
- std::chrono::duration::count函数的实际结果类型是什么
- 术语的计算结果不是采用0个参数的函数
- 错误 C2064:术语的计算结果不是采用 3 个参数的函数
- C++:术语的计算结果不是采用 1 个参数的函数
- ZTV,ZTS,ZTI 在 gdb x/nfu "vtable_address" 的结果中是什么意思?
- 错误 C2064:term 的计算结果不是采用 1 个参数的函数 - 关于线程的一些东西
- 如何打印返回值的结果?我是一个初学者学习C++
- 即使在C 中越过初始化阵列的极限后,结果也是如此
- 使用FP:快速导致错误的VC 结果(不仅仅是不准确)结果 - 这是编译器错误
- 我收到此错误:错误 c2064:term 的计算结果不是采用 0 个参数的函数,但我不明白为什么
- C++时间()给我的结果几乎是随机的
- 三元运算符的结果不是右值
- 为什么"decltype(i+j)"的结果不是右值引用?
- 简单的代码,看似随机的结果——这是由于过时的引用造成的吗
- wxwidgets Bind()项的计算结果不是在event.h中使用1个参数的函数
- 我正在尝试用C++制作一个费用计算器,我得到了错误C2064:term的计算结果不是一个带1个参数的函数
- 取消引用无效指针但不使用结果是否是C++中的未定义行为
- 字符* 到字符串 c++(结果不是预期的)
- 错误C2064:术语的计算结果不是一个带1个参数的函数,我该如何克服这个错误