为什么不能将 Base class 对象分配给 Derived class 对象?

Why can't a Base class object be assigned to a Derived class object?

A derived class object 可以分配给 C++ 中的 base class object

Derived d;
Base b = d; // It's Ok

但为什么不能将 base class object 分配给 derived class object

Base b;
Derived d = b; //Not Ok. Compiler give an error

编辑:

抱歉,这个问题实际上是在面试时提出的。

继承是一种 "is-a" 关系,但它是 单向的

如果你有,例如

struct Base { /* ... */ };
struct Derived : Base { /* ... */ };

那么Derived是一个Base,但是Base不是一个Derived.

这就是为什么您可以使用派生对象分配或初始化基 class 实例(但要注意 object slicing),但反之则不行。

派生对象是具有附加信息的基础对象。

您可以从派生对象的基础部分初始化一个完整的基础对象,没问题。

但是如果你只想从一个基础对象构造一个派生对象,应该用什么来初始化附加信息?

如果您想为该附加信息提供默认值,可以通过声明 Derived(Base const &) 构造函数来实现。但由于它在一般情况下不起作用,所以它不是为您完成的。

通常,C++ 编译器不允许将基 class 的对象分配给派生对象,因为从某种意义上说,派生 class 是基 [=] 的超集22=]:也就是说,它不知道如何处理任何特定于派生 class.

的成员

也就是说,您可以通过在派生的 class.

中适当重载赋值运算符和适当的构造函数来手动编码这种可能性

除了可能使语言过于复杂之外,我不明白为什么不能将可简单复制的基础 class 实例分配给不包含其他成员的派生 class。但在我撰写本文时,这还没有在任何 C++ 标准中实现。此外,至少在我看来,拥有任何未初始化的派生 class 成员和绕过派生 class 构造函数的后果并不比 [=19] 的危险需要程序员更多的考虑=]对象切片如果派生class实例被分配给基class!换句话说,我认为陈腐的反驳 "because it makes no sense" 本身没有多大意义。

参考:http://en.cppreference.com/w/cpp/types/is_trivially_copyable

使用临时参考怎么样?

Base b;
Derived d;
Base & d_ref = d;
d_ref = b;

如果存在 public 继承 b/w Base 和 Derived class ,那么就是“是”关系。

并且在“是一个”关系中派生是一个基础。

这里最重要的一点是“是一个关系”不是双向的。

即Derived 是一个 Base 但 Base 不是 Derived。

假设我们有两个 classes Shape 和 Circle。

Shape 是一个 Base,Circle 是 publically 继承自 Shape。

所以,Circle 是 Shape 但 Shape 不是 Circle

//main.cpp
#include <iostream>
#include <string>

using namespace std;

class Shape
{
private:
    int x;
public:
    Shape(int i):x{i}
    {
        cout << "Base constructor called " << endl; 
    }
};

class Circle : public Shape
{
private :
    string color;  
public : 
    Circle(int radius) : Shape{ radius } 
    {
        cout << "Derived constructor called " << endl;
    }
    Circle(int radius, string color) : Shape{ radius }, color{ color }  
    {
        cout << "Derived constructor called " << endl;
    }
};


int main()
{
    //This is valid .  since a circle is a shape 
    Circle s(1);
    Shape a = s;

    return 0; 
} 

但是你不能这样做,因为 Shape 不是圆形 而且这里的继承不是双向的

 Shape s(1);
 Circle a = s;

如果你这样做,你会得到一个编译器错误

  no suitable user-defined conversion
        from "Shape" to "Circle" exists