构造函数和析构函数

构造函数和析构函数在类中的调用顺序:

1)构造函数:

定义一个对象时先调用基类的构造函数、然后调用派生类的构造函数。

1)析构函数:

析构与构造的过程恰好相反:先调用派生类的析构函数、然后调用基类的析构函数。

注意:由于vs2013无法显示输出析构函数的内容,所以采用输出到文本中的方式。

 1 #include<iostream>
 2 #include <fstream>
 3 using namespace std;
 4 
 5 fstream fout("D:\Downloads\destructor.txt", ios::app);
 6 class Base {
 7 public:
 8     Base(int c) { fout << "基类带参构造函数" << c << endl; }
 9     ~Base() { fout << "基类析构" << endl; }
10 };
11 class Derived :public Base {
12 public:
13     Derived(int c) :Base(c) // 显式调用基类构造函数
14     {
15         fout << "派生类带参构造函数" << c << endl;
16     }
17     ~Derived() { fout << "派生类析构" << endl; }
18 };
19 int main()
20 {
21     int i = 9;
22     Derived d1(i);
23     system("pause");
24     return 0;
25 }

输出结果:

基类带参构造函数9
派生类带参构造函数9
派生类析构
基类析构


 1 #include<iostream>
 2 #include <fstream>
 3 using namespace std;
 4 
 5 fstream fout("D:\Downloads\destructor.txt", ios::app);
 6 //创建一个汽车类
 7 class Car
 8 {
 9 public:
10     //构造函数
11     Car(short, int);
12     //析构函数
13     ~Car();
14     void move();
15 private:
16     short speed;
17     int num;
18 };
19 
20 Car::Car(short s, int n)
21 {
22     speed = s;
23     num = n;
24     fout << "创建第" << num << "辆车,速度是" << speed << " 米/秒" << endl;
25 }
26 Car::~Car()
27 {
28     fout << "销毁掉第 " << num << "辆车" << endl;
29 }
30 void Car::move()
31 {
32     fout << "" << num << "辆车速度是" << speed << endl;
33 }
34 //主函数
35 void main()
36 {
37     //先创建第car1对象,再创建car2对象
38     Car car1(10, 1), car2(20, 2);
39     car1.move();
40     car2.move();
41 }

输出结果:

创建第1辆车,速度是10 米/秒
创建第2辆车,速度是20 米/秒
第 1辆车速度是10
第 2辆车速度是20
销毁掉第 2辆车
销毁掉第 1辆车

解析:

在主函数中是首先创建了Car类的car1对象,后创建了car2对象,所以在执行构造函数的顺序上,是先执行car1对象的构造函数,后执行car2对象的构造函数。而在主函数执行结束,要调用析构函数的时候,根据开始说的法则,则会先执行car2类的析构函数,后执行car1类的析构函数。这就是“使用构造函数创建对象的顺序与使用析构函数释放对象的顺序相反”这条法则的一个很好的体现。


 1 #include <iostream>
 2 using namespace std;
 3 class A{
 4 public:
 5        A(){cout<<"Construct a"<<endl;p();}
 6        virtual void p(){cout<<"A"<<endl;}
 7        ~A(){cout<<"Destruct a"<<endl;p();}   
 8 };
 9 class B : public A{
10 public:
11        B(){cout<<"Construct b"<<endl;p();}
12        void p(){cout<<"B"<<endl;}
13        ~B(){cout<<"Destruct b"<<endl;p();}    
14 };
15 int main()
16 {
17     A *a=new B();
18     delete a;
19     getchar();
20     return 0;
21 }

打印的结果是:
Construct a
A
Construct b
B
Destruct a
A

  • 这是一段极易出错的程序,如果用的话 出现的就是先析构 B类 再析构A类 
 B *a=new B();

打印的结果是:
Construct a 

Construct b 

Destruct b 

Destruct a 

A *a = new B;
虽然指针a指向B类型,但指针a的类型是A。
delete a时将调用类型A的析构函数;
因为:如果A的析构函数是虚函数,则:
delete a时调用类型A的析构函数步骤如下:
1,到虚函数映射表中查找A的实际析构函数;
2,发现被实例化为B的析构函数;
3,调用B的析构函数;
4,调用A的析构函数---如果A的析构不是纯虚函数的话。

原文地址:https://www.cnblogs.com/Bella2017/p/9512972.html