将基类对象分配给派生类对象

时间:2015-01-14 18:16:24

标签: c++ inheritance

    class Base{};
    class Derived: public Base{};

    int main()
    {
        Base B;
        Derived D;

        Base B1 = D;//OK
        Derived D1 = B;//error: conversion from ‘Base’ to non-scalar 
                       //type ‘Derived’ requested
        return 1;
    }

我知道派生类与基类有一个is-a关系。

什么阻止Derived D1具有来自B的值和剩余的成员变量(如果有)具有一些垃圾值?

或者

错误消息是什么

  

从'Base'转换为非标量类型'Derived'请求Derived D1 = B;

说什么?什么是标量类型?

2 个答案:

答案 0 :(得分:4)

声明

Derived D1 = B;

是初始化,而不是赋值(即使它看起来像赋值)。

它尝试使用Derived复制构造函数,但该复制构造函数接受参数Derived const&。并且B实例无法自动转换为完整的Derived

如果你真的想要一个切片分配 - 只分配给Base的{​​{1}}切片 - 那么你可以明确地使用D1

Base::operator=

另一种表达方式:

Derived D1;
D1.Base::operator=( B );

但闻起来很糟糕。 ; - )


RE

  

什么是标量类型?

这与“规模”中的词语相同。标量类型提供单个幅度值,因此可以将类型的值与Derived D1; static_cast<Base&>( D1 ) = B; (理想情况下也是==)进行比较。但是,在C ++中,指针甚至成员指针都被视为标量类型:

C ++11§3.9/ 9 [basic.types]:

  

算术类型(3.9.1),枚举类型,指针类型,指向成员类型的指针(3.9.2),std :: nullptr_t以及这些类型的cv限定版本(3.9 .3)统称为标量类型

答案 1 :(得分:0)

如果B的成员变量被声明为私有,则会阻止D1拥有B的值。

就您的第二个问题而言,您可以指定Base B1 = D;,因为编译器知道D是来自B的派生类。但是,在Derived D1 = B;中,编译器没有表明该关系。

至于你的标量是什么的问题,标量是整数,字符,指针等。它们与结构和类不同,它们是用户定义的类型。