构造函数和析构函数
构造函数和析构函数在类中的调用顺序:
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
A
Construct b
B
Destruct b
B
Destruct a
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的析构不是纯虚函数的话。