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

Assigning base class object to derived class object

本文关键字:对象 派生 分配 基类      更新时间:2023-10-16
    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 关系。

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

错误消息是什么

从"基本"转换为非标量类型"派生"请求派生 D1 = B;

说?什么是标量类型?

语句

Derived D1 = B;

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

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

如果您确实想要切片分配 - 仅分配给D1Base切片 - 那么您可以显式使用以下Base::operator=

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

另一种表达方式:

Derived D1;
static_cast<Base&>( D1 ) = B;

但它闻起来很臭。


" 什么是标量类型?

这与"规模"中的词相同。标量类型提供单个量级值,以便可以将该类型的值与==进行比较(理想情况下也可以与 < 进行比较)。但是,在C++指针甚至成员指针都被视为标量类型:

C++11 §3.9/9 [基本类型]:

" 算术类型 (3.9.1)、枚举类型、指针类型、指向成员类型的指针 (3.9.2)、std::nullptr_t 和这些类型的 cv 限定版本 (3.9.3) 统称为标量类型

如果B的成员变量被声明为私有的,那么这将阻止D1拥有B的值。

至于你的第二个问题,你可以分配Base B1 = D;,因为编译器知道D是来自B的派生类。然而,在Derived D1 = B;中,编译器没有指示这种关系。

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