当转换为父类对象而不是引用时会发生什么不良结果?

时间:2012-08-18 18:58:42

标签: c++ casting polymorphism

此代码由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;
}

3 个答案:

答案 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;
}