为什么指向基类的指针可以指向子类的对象?
Why a pointer to the base class can point an object of the child class?
假设在C++中,如果我们有一个基类 Base 和一个派生的子类:
class Base{
protected:
int x_base;
};
class Derived : public Base {
public:
int x_prot;
};
比在主要中,我们可以创建一个指向基类的指针,并让它指向派生类对象:
Base *b;
b=new Derived;
但这是不允许的:
Derived *b;
b=new Base;
我会反其道而行之。
当我们调用Base* b
时,我们对代码说b
将是指向类Base
对象的指针。在示例中,他将准备好为x_base
分配空间(但不为x_prot
分配空间(。因此,我们不应该能够使用基类的指针指向子类的对象。
我的推理错误在哪里?
当我们调用
Base* b
时,我们对代码说b
将是指向类Base
对象的指针。
我们确实是这样说的。这是真的!每个Derived
对象都以一个Base
子对象开头。这就是继承的本质。Derived
是一个Base
加上最后的一些附加内容。
制作一个完全忽略末尾附加内容的指针是完全可以的:这就是向上投射所做的。
在示例中,他将准备好为
x_base
分配空间(但不为x_prot
分配空间(
指针不分配东西。他们指向事物。
事实上,你的推理正是Derived* b=new Base;
被破坏的原因——确实创造了一个对象的东西(即new
(只是创建一个Base
,而不是一个Derived
。然后说b
指向一个可以被视为完整Derived
的东西,那简直是不真实的。你最后错过了所有其他的东西。
我的推理错误在哪里?
我认为您将指针视为创建对象的东西,但事实并非如此。它们是指向由其他事物创建的对象的东西(例如new
(。
假设您邀请了一位水管工在下周二到您家。你只知道他是一个base plumber
.您还知道有两种类型的水管工 - 基础和扩展。基地水管工可以修理管道。扩展的可以做基地做的事情,也可以安装热水器。你不知道哪个会来你的房子基地一个或扩展,所以可以安全地假设他是基地。所以当男人到达时,你可以要求他修理你的管道,你会没事的。但是,假设您还希望安装加热器。你不能要求这家伙安装它,因为他只是作为基地水管工来的。所以你有两个选择:
-
你告诉那个人 - 我不在乎你是谁,或者我看到你在其他地方做你的工作,或者我意识到的其他方式,所以我假设你是一个扩展的水管工。所以我现在打电话给你扩展,去安装我的加热器。因此,如果你的假设是正确的,你会没事的。如果你错了,那么这家伙可能会倒置安装热水器,可以完全制动它,甚至让你的整个房子爆炸。
你 问那个人:你是一个长期的水管工吗?如果他说是,那么你告诉他 - 安装加热器。所以你要么没事,要么不会完成工作。
所以回到你的案例 - 将扩展水管工视为基础是安全的,他们都可以修理管道。另一方面,假设水管工被延长是不安全的,所以你要么需要一种方法来知道这一点,要么问他。第一个由static_cast<>
完成,第二个由dynamic_cast<>
完成。但现在应该更清楚为什么将派生类指针(扩展管道工(转换为 base 是安全的,反之则不然。
- 从父类方法返回子类对象
- 对静态分配的子类对象进行静态分配的纯虚拟父类引用是否合法?
- 我们可以在没有新实例化的情况下声明一个抽象方法来返回抽象超类中的子类对象吗
- 如何在 BaseClass 指针数组中存储指向子类对象的指针?
- 子类对象列表重新解释为基类对象列表?(C++11).
- 如何将字符串(ID)映射到新的子类对象C 的创建
- C++:使用父类运算符函数更新子类对象的继承变量
- 指向子类对象的指针的静态数组出现问题
- cpp 从需要超类对象的函数访问子类对象方法
- 制作可以存储子类对象的超类类型的向量
- 我构造子类对象的方式有什么问题?
- 识别基类指向的子类对象
- C++维护子类对象的混合集合
- 在构造子类对象的过程中,更改一个类属性的数据类型会导致segfault
- 将子类对象传递给采用超类对象的函数
- 从基类模板化列表中实例化子类对象
- 创建子类对象时, 是为超类创建的第二个对象
- 如何从私有成员子类对象捕获异常
- 如何让一组不同的子类对象从另一组共享基类的一个静态变量
- visual超级类有可能拥有子类对象吗?c++