为什么不能将 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
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