此代码由Bruce Eckel在他的书“Thinking in C ++”第14章第649页中撰写。我不明白的是他在下面做出的评论[强调补充]:
operator<<
的{{1}}很有意思,因为它为Child
中的operator<<
调用Parent
:将Child
对象强制转换为一个Parent&
(如果您转换为基类对象而不是引用,通常会产生不良结果)。
以下是相应的代码:
#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;
}
答案 0 :(得分:1)
是的,这没关系。父母和孩子是多形态的。作为Child继承的客户端,您可以将Child&
转换为Parent&
在表达式os << (Parent&)c
中,rhs (Parent&)c
的类型为Parent&
因此operator<<(ostream& os, const Parent& b)
将从operator<<(ostream& os, const Child& b)
在C ++中,只有在具有引用或指针类型
时,多态性才有效答案 1 :(得分:1)
不良结果是编译器必须创建Child对象的Parent部分的临时副本,将对该临时文件的引用传递给插入器,然后销毁临时对象。那是很多搅拌......
正如@NeelBasu暗示的那样,如果Parent
具有在Child
中覆盖的虚函数,则从插入器调用这些函数将不会调用Child
版本,因为传入的对象是Parent
对象。
答案 2 :(得分:1)
这可能是对象切片的意思。也就是说,通过将对象复制到父类的实例(而不是分配引用),您将丢失对象的某些部分。
还要看看这个问题的答案:
以下是一个例子:(见http://ideone.com/qeZoa)
#include <iostream>
using namespace std;
struct parent {
virtual const char* hi() const { return "I'm your father..."; }
};
struct child : public parent {
const char* hi() const { return "No way!"; }
};
int main() {
child c;
cout << ((parent) c).hi() << endl;
cout << ((parent&)c).hi() << endl;
}