C++ 构造函数和析构函数是如何在C++;?

C++ 构造函数和析构函数是如何在C++;?,c++,implementation,C++,Implementation,我有两个类:Base和Derived(从Base公开派生)。 当我写作时- Derived * d1 = new Derived; delete d1; 编译器发现d1是一个派生类型对象。因此它调用派生类构造函数(它调用基类构造函数)。我这里有两个问题- 1) 我们为什么遵循这个顺序 2) 这些构造函数如何协同工作来分配内存?我需要一些实施细节 现在,下一条语句是delete d1。所以编译器看到d1是一个派生类型对象,所以调用派生类的析构函数(它在删除派生类成员后调用基类的析构函数)。我这里

我有两个类:Base和Derived(从Base公开派生)。 当我写作时-

Derived * d1 = new Derived;
delete d1;
编译器发现d1是一个派生类型对象。因此它调用派生类构造函数(它调用基类构造函数)。我这里有两个问题-

1) 我们为什么遵循这个顺序

2) 这些构造函数如何协同工作来分配内存?我需要一些实施细节

现在,下一条语句是delete d1。所以编译器看到d1是一个派生类型对象,所以调用派生类的析构函数(它在删除派生类成员后调用基类的析构函数)。我这里有一个问题-


1) 这些析构函数如何协同工作?假设派生类析构函数被传递给内存中d1的地址。这些析构函数现在是如何释放空间的?

代码将无法编译。您不能
删除
自动实例,您必须使用
新建
来分配实例,以便对其使用
删除

当涉及到构造函数顺序时,我想运行它们是有意义的,这样更专业的类就可以依赖于已经完成的更通用的部分


编译器可以通过检查完整的类声明和通过任何和所有超类进行递归来了解每个类的内存布局。

该代码不会编译。您不能
删除
自动实例,您必须使用
新建
来分配实例,以便对其使用
删除

当涉及到构造函数顺序时,我想运行它们是有意义的,这样更专业的类就可以依赖于已经完成的更通用的部分


编译器可以通过检查完整的类声明和递归任何和所有超类来了解每个类的内存布局。

您给出的代码示例无法编译<代码>删除作用于指针,而不是对象

<>我认为C++本身(语言标准)不涉及内存如何用来表示使用继承的类型的实例。然而,在大多数实现中,从空闲存储区分配一块内存,该存储区足够大,可以容纳
Base
派生
的所有数据。删除
派生的
实例时,两个构造函数都会运行,然后释放单个内存块


类似地,如果
派生的
实例是某类
容器
的嵌入式数据成员,则保存
容器
实例的内存块将变得足够大,以容纳
派生的
(因此
)而您给出的代码示例中的
容器的所有其他数据都不会编译<代码>删除
作用于指针,而不是对象

<>我认为C++本身(语言标准)不涉及内存如何用来表示使用继承的类型的实例。然而,在大多数实现中,从空闲存储区分配一块内存,该存储区足够大,可以容纳
Base
派生
的所有数据。删除
派生的
实例时,两个构造函数都会运行,然后释放单个内存块


类似地,如果
派生的
实例是某类
容器
的嵌入式数据成员,则在构造时,保存
容器
实例的内存块将变得足够大,以容纳
派生的
(因此
)和
容器
的所有其他数据,构造函数从最高的基类调用,直到派生最多的基类中的一个,该基类将被称为最新的


调用析构函数时,顺序正好相反。第一个被称为最派生的析构函数,直到最高基类中的一个。

构造时,从最高基类调用构造函数,直到最派生的一个,这将被称为最新的

调用析构函数时,顺序正好相反。第一个被称为最派生的析构函数,直到最高基类之一。

1)默认情况下,基类构造函数被自动调用。但是,允许派生构造函数在其初始值设定项列表中显式调用基类构造函数。如果构造函数不是在派生类中首先执行的,那么这是不可能的

Derived::Derived() : foo( 42 ), bar( 7 ), Base( 1, 2 ) { }
2) 编译器知道派生类的内存占用(因为所有成员变量在编译时都是已知的),并分配足够的内存来容纳基类和派生类成员。内存布局的详细信息由系统使用的ABI指定

3) 析构函数不仅仅是释放内存。实际上,析构函数不会释放保存任何成员变量所需的内存—只在必要时释放成员指针指向的内存。

1)默认情况下,基类构造函数会自动调用。但是,允许派生构造函数在其初始值设定项列表中显式调用基类构造函数。如果构造函数不是在派生类中首先执行的,那么这是不可能的

Derived::Derived() : foo( 42 ), bar( 7 ), Base( 1, 2 ) { }
2) 编译器知道派生类的内存占用(因为所有成员变量在编译时都是已知的),并分配足够的内存来容纳基类和派生类成员。内存布局的详细信息由系统使用的ABI指定

3) 析构函数不仅仅是释放内存。实际上,析构函数不会释放保存任何成员变量所需的内存—只在必要时释放成员指针指向的内存。

(1)基类不依赖于派生类,但也可以使用其他方法。也就是说,
Base
类无法知道哪个fi