指向派生类的指针是否首先创建基类
Does pointer to derived class create the Base class first or not?
>我有以下代码
#include <iostream>
using namespace std;
class B{
int i;
public:
B(){
cout << "Constructing Bn";
}
void print(){
cout << "Printing from B with size : "<<sizeof(*this)<<endl;
}
};
class D:public B{
int i;
public:
D(){
cout << "Constructing Dn";
}
void print(){
cout << "Printing from D with size : "<<sizeof(*this)<<endl;
}
};
int main(){
B b;
b.print();
D d;
d.print();
D* dp;
dp->print();
}
这给了我以下输出:
Constructing B
Printing from B with size : 4
Constructing B
Constructing D
Printing from D with size : 8
Printing from D with size : 8
那么,当您创建指向派生类的指针时,它不会首先创建基类的实例,这是真的吗?我不认为这是真的,因为D类的大小就是证明。但它甚至不调用基类构造函数。谁能解释一下?
不会创建任何内容。指针只是指针 - 包含地址的标量对象。你有责任使指针指向内存中的正确位置。
在示例中,指针dp
未初始化。你从来没有把它指向任何地方,所以它无处可去。尝试调用dp->print()
会产生未定义的行为。故事结束。
现在你的指针根本没有初始化,所以尝试使用它会产生未定义的行为。尝试类似操作:
D *dp = new D;
dp->print();
delete dp;
或者为了做得更好,例如:
std::unique_ptr<D> dp = std::make_unique<D>();
dp->print();
。并且unique_ptr
将在超出范围时自动删除D
。
但请注意,您已将print
定义为非虚函数,因此调用的函数将取决于所使用的指针(或引用)的类型,而不是它引用的对象的类型。此外,您尚未定义虚拟 dtor。
因此,如果您要执行以下操作:
B *p = std::make_unique<D>();
p->print(); // would invoke B::print, even though the object is a D
。当它超出范围时,它会被错误地销毁,所以你会得到未定义的行为。要更正此问题,您需要将 B 更改为如下所示的内容:
class B{
int i;
public:
B(){
cout << "Constructing Bn";
}
virtual void print(){
cout << "Printing from B with size : "<<sizeof(*this)<<endl;
}
virtual ~B() = default;
};
执行此操作时,答案是"是"——当您创建派生对象时,它将首先调用基类的 ctor,然后调用派生类的 ctor。当派生对象被销毁时,情况正好相反:首先将调用派生类的 dtor,然后在它完成时将执行基类的 dtor。
它是在派生类之前构造基类。您的输出反映了这一点。看看这个
//Constructs Base class
Constructing B
//Constructs Derived class
Constructing D
//Prints from derived
Printing from D with size : 8
代码在不调用构造函数的情况下打印Printing from D with size : 8
两次的原因是,代码永远不会创建 D
的第二个实例。
D* d;
^^^^ Declares a pointer to a D, Does not create a D!
当您调用d->print();
时,它是未定义的行为,因为d
不指向D
的实例。最后,代码打印在编译时确定的值(sizeof(D)
是编译时值),并且不接触代码运行的this
指针。
请参阅此处的sizeof
文档。
强大的多态性为Derived
对象分配Base
指针。这是可能的,因为Derived
实现了Base
包含的所有内容。因此,隐含的是,底层Derived
在其自身的实例化过程中实例化Base
。
class Base
{
public:
Base()
{}
}
class Derived : public Base
{
public:
Derived()
{}
}
Derived *derived = new Derived();
Base *base = derived;
- 在C++中,是否可以基于给定的标识符创建基类的新实例,反之亦然
- 使用基类指针创建对象时,缺少派生类析构函数
- 如何使用 std::make_shared 创建基类类型的智能指针?
- 与简单地创建派生类指针相比,将基类绑定到派生类有什么优点?
- 从引用创建指向基类的智能指针
- 创建基类指针的向量并将派生类对象传递给它(多态性)
- 在基类中创建派生类的对象
- 一般函数中类的概括为基类创建对象代码
- 创建并编译基类以在其他 C++ 项目 (ROS) 中使用
- 如何使用 CRTP 创建具有基类的可选模板参数
- 如何为基类通用类型创建向量以使用具体类型元素
- 如何为抽象基类创建模板实例化?
- 将使用基类 Ctor创建的对象转换为派生类
- CRTP - 是否可以创建一个抽象基类?
- 动态创建一个继承的类,使用STD :: MAP使用基类指针访问
- 如何创建一个动态数组,该数组可以保存从C++中派生的同一基类的所有不同对象
- 如何从现有基类对象创建派生类对象
- 基于参数创建基类中的派生类
- 如果基类构造函数受到保护,为什么我们不能在派生类函数中创建基类对象
- 指向派生类的指针是否首先创建基类