构造函数与析构函数默行于世

1) 在派生类构造函数中,所有的虚基类及上一层基类的构造函数调用;

2) 对象的vptr被初始化;

3) 如果有成员初始化列表,将在构造函数体内扩展开来,这必须在vptr被设定之后才做;

4) 执行程序员所提供的代码;

析构函数

析构函数用于撤销对象的一些特殊任务处理,可以是释放对象分配的内存空间;

特点:析构函数与构造函数同名,但该函数前面加~。析构函数没有参数,也没有返回值,而且不能重载,在一个类中只能有一个析构函数。当撤销对象时,编译器也会自动调用析构函数。每一个类必须有一个析构函数,用户可以自定义析构函数,也可以是编译器自动生成默认的析构函数。一般析构函数定义为类的公有成员。

我们往往通过基类的指针来销毁对象。这时候假设析构函数不是虚函数,就不能正确识别对象类型从而不能正确调用析构函数。C++中基类采用virtual虚析构函数是为了防止内存泄漏。具体地说,如果派生类中申请了内存空间,并在其析构函数中对这些内存空间进行释放。假设基类中采用的是非虚析构函数,当删除基类指针指向的派生类对象时就不会触发动态绑定,因而只会调用基类的析构函数,而不会调用派生类的析构函数。那么在这种情况下,派生类中申请的空间就得不到释放从而产生内存泄漏。所以,为了防止这种情况的发生,C++中基类的析构函数应采用virtual虚析构函数。

纯虚析构函数一定得定义,因为每一个派生类析构函数会被编译器加以扩张,以静态调用的方式调用其每一个虚基类以及上一层基类的析构函数。因此,缺乏任何一个基类析构函数的定义,就会导致链接失败。因此,最好不要把虚析构函数定义为纯虚析构函数。

类析构时机:

1) 对象生命周期结束,被销毁时;

2) delete 指向对象的指针时,或 delete 指向对象的基类类型指针,而其基类虚构函数是虚函数时;

3) 对象i是对象o的成员,o的析构函数被调用时,对象i的析构函数也被调用。

一个派生类构造函数的执行顺序如下:

① 虚拟基类的构造函数(多个虚拟基类则按照继承的顺序执行构造函数)。

① 基类的构造函数(如果有多个基类,则构造函数的调用顺序是某类在类派生表中出现的顺序,而不是它们在成员初始化表中的顺序。)

②  类类型的成员对象的构造函数(如果有多个成员类对象则构造函数的调用顺序是对象在类中被声明的顺序,而不是它们出现在成员初始化表中的顺序。)

③  派生类自己的构造函数。

析构函数顺序

①  调用派生类的析构函数;

②  调用成员类对象的析构函数;

③  调用基类的析构函数。

构造函数为什么不能为虚函数?

1.从存储空间角度,虚函数相应有一个指向vtable虚函数表的指针,这大家都知道,但是这个指向vtable的指针事实上是存储在对象的内存空间的。问题出来了,假设构造函数是虚的,就需要通过vtable来调用,但是对象还没有实例化,也就是内存空间还没有,怎么找vtable呢?所以构造函数不能是虚函数。

2.从使用角度,虚函数主要用于在信息不全的情况下,能使重载的函数得到相应的调用。构造函数本身就是要初始化实例,那使用虚函数也没有实际意义呀。所以构造函数没有必要是虚函数。虚函数的作用在于通过父类的指针或者引用来调用它的时候可以变成调用子类的那个成员函数。而构造函数是在创建对象时自己主动调用的,不可能通过父类的指针或者引用去调用,因此也就规定构造函数不能是虚函数。

3.构造函数不需要是虚函数,也不同意是虚函数,由于创建一个对象时我们总是要明确指定对象的类型,虽然我们可能通过基类的指针或引用去访问它。

4.从实现上看,vbtl在构造函数调用后才建立,因而构造函数不可能成为虚函数;从实际含义上看,在调用构造函数时还不能确定对象的真实类型(由于子类会调父类的构造函数);并且构造函数的作用是提供初始化,在对象生命期仅仅运行一次,不是对象的动态行为,也没有必要成为虚函数。

5.当一个构造函数被调用时,它做的首要的事情之中的一个是初始化它的vptr(指向虚函数的指针)。因此,它仅仅能知道它是“当前”类的,而全然忽视这个对象后面是否还有继承者。当编译器为这个构造函数产生代码时,它是为这个类的构造函数产生代码——既不是为基类,也不是为它的派生类(由于类不知道谁继承它)。所以它使用的vptr必须是对于这个类的vtable。并且,仅仅要它是最后的构造函数调用,那么在这个对象的生命期内,vptr将保持被初始化为指向这个vtable,但假设接着另一个更晚派生的构造函数被调用,这个构造函数又将设置vptr指向它的vtable,等.直到最后的构造函数结束。vptr的状态是由被最后调用的构造函数确定的。这就是为什么构造函数调用是从基类到后继派生类顺序的另一个理由。可是,当这一系列构造函数调用正发生时,每一个构造函数都已经设置vptr指向它自己的vtable。假设函数调用使用虚机制,它将仅仅产生通过它自己的vtable的调用,而不是最后的vtable(全部构造函数被调用后才会有最后的vtable)。

因为构造函数本来就是为了明确初始化对象成员才产生的,然而virtual function主要是为了再不完全了解细节的情况下也能正确处理对象。另外,virtual函数是在不同类型的对象产生不同的动作,现在对象还没有产生,如何使用virtual函数来完成你想完成的动作。

构造函数和析构函数可以调用虚函数吗,为什么?

1) 在C++中,提倡不在构造函数和析构函数中调用虚函数;

2) 构造函数或者析构函数调用虚函数并不会发挥虚函数动态绑定的特性,跟普通函数没区别;

3) 因为父类对象会在子类之前进行构造,此时子类部分的数据成员还未初始化,因此调用子类的虚函数是不安全的,故而C++不会进行动态联编;

4) 析构函数是用来销毁一个对象的,在销毁一个对象时,先调用子类的析构函数,然后再调用基类的析构函数。所以在调用基类的析构函数时,派生类对象的数据成员已经销毁,这个时候再调用子类的虚函数没有任何意义。

构造函数析构函数可否抛出异常?

1) C++只会析构已经完成的对象,对象只有在其构造函数执行完毕才算是完全构造妥当。在构造函数中发生异常,控制权转出构造函数之外。因此,在对象b的构造函数中发生异常,对象b的析构函数不会被调用。因此会造成内存泄漏。

2) 用 auto_ptr 对象来取代指针类成员,便对构造函数做了强化,免除了抛出异常时发生资源泄漏的危机,不再需要在析构函数中手动释放资源;

3) 如果控制权基于异常的因素离开析构函数,而此时正有另一个异常处于作用状态,C++会调用terminate函数让程序结束;

4) 如果异常从析构函数抛出,而且没有在当地进行捕捉,那个析构函数便是执行不全的。如果析构函数执行不全,就是没有完成他应该执行的每一件事情。

THE END
0.析构函数(C++)|MicrosoftLearn显式定义析构函数、复制构造函数或复制赋值运算符可防止对移动构造函数和移动赋值运算符进行隐式定义。 在这种情况下,如果复制成本高昂,未能提供移动操作通常意味着错过了优化的机会。 另请参阅 复制构造函数和复制赋值运算符 移动构造函数和移动赋值运算符 本文内容 声明析构函数 使用构造函数 破坏的顺序 显式析构函数调用 可靠编程 另请参阅 此页面是否有帮助? 是否jvzquC41fqit0vnetqyph}3eqo5{j6hp1evq1lur1fktv{zevqxt/lur
1.深入理解构造和析构函数为什么要引入构造函数和析构函数构造函数和析构函数是当你刚接触C++的时候就会碰到的两个概念,也是C++语法中较难掌握的两个概念。但是它们又是学习C++必须掌握的,可以说没有理解构造和析构函数,你的C++就还没有入门。 本文拟对构造函数、析构函数进行系统的介绍,使得那些对这两个概念有初步认识的人能有更进一步的理解。 jvzquC41dnuh0lxfp0tfv8feu9741jwvkerf1mjvckrt1@>825923
2.C++析构函数详解设计一个类时,如何写析构函数? 析构函数如果我们不写的话,C++会帮我们自动的合成一个,就是说:C++会自动的帮我们写一个析构函数。很多时候,自动生成的析构函数可以很好的工作,但是一些重要的事迹,就必须我们自己去写析构函数。 析构函数和构造函数是一对。构造函数用于创建对象,而析构函数是用来撤销对象。简单jvzquC41dnuh0lxfp0tfv8lkvj{ca<:382<328ftvkimg8igvcomu8:482845;
3.C++构造函数和析构函数(非常详细)为了完成对象的创建和销毁,C++ 中的类提供了两个特殊的函数,分别是构造函数(Constructor)和析构函数(Destructor),它们会在对象创建和销毁时会被自动调用。 C++构造函数 构造函数在对象创建时自动调用,用于完成对象的初始化工作。构造函数的使用确保了对象在被使用之前已经具备了合理的初始状态。例如,它可以为对象的属性jvzquC41e0hjcwhjgpm/pny1xkkx1~ydjm650qyon
4.C++学习——构造函数析构函数本文详细介绍了C++中构造函数和析构函数的作用、定义、使用场景,包括初始化列表、内存管理以及执行时机。构造函数用于对象创建时初始化成员变量,析构函数负责对象销毁时的清理工作。 以下内容源于C语言中文网的学习与整理,非原创,如有侵权请告知删除。 一、构造函数的详解 jvzquC41dnuh0lxfp0tfv8tssJ{Uw:7567<8:8ftvkimg8igvcomu8655:772<6
5.C++构造函数和析构函数c++构造函数和析构函数C++|构造函数和析构函数 一、构造函数 构造函数是一种特殊的成员函数,主要用于创建对象时对对象进行初始化操作,即专门用于构造新对象,并赋值对象的成员数据。 在C++ 里,构造函数的名称和类名相同,并且没有返回类型。当创建类的对象时,构造函数会自动被调用。 构造函数可以在类内也可在类外定义。 构造函数在类内的定义格式 jvzquC41dnuh0lxfp0tfv8r2a9:43@7281gsvrhng1jfvjnnu1758<5483>
6.C++超详细讲解构造函数与析构函数的用法及实现C语言上一节解决了类与对象封装的问题,这一节就是对象的初始化和清理的构造函数与析构函数的内容了;对象的初始化和清理也是两个非常重要的安全问题:一个对象或者变量没有初始状态,对其使用后果是未知,同样的使用完一个对象或变量,没有及时清理,也会造成一定的安全问题;c++利用了构造函数和析构函数解决上述问题,这两个jvzquC41yy}/lk:30pku1jwvkerf1;9;766/j}r
7.C++:构造函数和析构函数空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。 默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。 这篇文章介绍的是构造函数和析构函数。 一,构造函数 在C语言中,我们平时在建立一个栈,或是写一些函数时,可能有时偶尔会忘记调用初始化jvzquC41dnuh0lxfp0tfv87523e89B5266:0c{ykenk0fnyckny03<=2;5778
8.c++学习——构造函数与析构函数构造函数和析构函数在c++中有2个特殊的函数:构造函数和析构函数,它们分别对类对象进行初始化和清理工作。 1. 构造函数 构造函数,与类名相同,当创建类对象时会自动调用该函数。如果创建类对象时没有手动创建构造函数,系统会自动创建一个默认的构造函数,这个默认的构造函数函数体是空的,无任何功能。 jvzquC41dnuh0lxfp0tfv8hy32817>7561gsvrhng1jfvjnnu1<9;=;8;8
9.C#构造函数和析构函数拭不去の泪痕1、构造函数和析构函数是类中比较特殊的两种成员函数,分别用来对对象进行初始化和回收对象资源。 构造函数———对象初始化!!! 析构函数———回收对象资源!! 2、对象的生命周期从构造函数开始,从析构函数结束。如果一个类含有构造函数,在实例化该类的对象时就会被调用。如果含有析构函数,则会在销毁对象时调用。jvzquC41yy}/ewgnqiy/exr1uenbpp}kcpm0r8633783;A3jvor
10.构造函数与析构函数基础,以及使用过程中的注意事项析构函数使用而C++利用了C++利用了构造函数和析构函数解决上述两个问题,这两个函数将会被编译器自动调用; 当然如果我们不提供构造和析构,编译器会提供编译器提供的构造函数与析构函数是空实现。 构造函数的意义:在创建对象时,为对象的成员属性赋值,构造函数由编译器自动调用,无需手动调用。 析构函数的意义:作用域对象小回迁系统自动调用,执行清理工作。 jvzquC41dnuh0lxfp0tfv8^N[yp0c{ykenk0fnyckny03;<;92=39
11.析构函数拷贝构造函数c++拷贝构造和析构函数本文围绕C++的构造函数和析构函数展开。构造函数用于对象初始化,可带参数、重载,有默认构造函数;析构函数在对象生命周期结束时进行清理工作。还介绍了局部、静态、全局对象的初始化,缺省构造函数,构造函数与new运算符的交互,以及拷贝构造函数等内容。 1.构造函数: jvzquC41dnuh0lxfp0tfv8r2a7?29=55;1gsvrhng1jfvjnnu1745?84;:9
12.C++最通俗易懂的构造和析构函数讲解c++构造与析构函数讲解本文深入探讨了构造函数和析构函数的概念,包括它们的定义、语法、分类及调用方式。通过具体案例,详细解析了不同类型的构造函数,如无参、有参和拷贝构造函数,以及析构函数在对象生命周期结束时的作用。 构造和析构函数 构造和析构函数的概述 构造和析构函数定义 jvzquC41dnuh0lxfp0tfv8|gkzooa=84::8138ftvkimg8igvcomu8626;;26<:
13.C++的构造函数与析构函数调用顺序饔踣晦构造函数与析构函数的基本概念 ### 构造函数与析构函数的基本概念 - 构造函数的定义与作用:初始化对象成员,分配资源。 - 析构函数的定义与作用:释放资源,清理对象。 单个类中的调用顺序 ### 单个类中的调用顺序 - 构造函数调用时机:对象创建时自动调用,顺序与声明顺序一致。 jvzquC41dnuh0lxfp0tfv8ghclysaB521cxuklqg1fkucrqu13;5:A:478