首页 > 代码库 > 详谈c++的构造和析构

详谈c++的构造和析构

c++的构造

  概念:对象被创建时,编译系统对象分配内存空间,并自动调用该构造函数->由构造函数完成成员的初始化工作

  例:

 1 #include <iostream>
 2 using namespace std;
 3 
 4 class A{
 5 public:
 6     A():a(1),b(0){cout<<"A"<<endl;}
 7 private:
 8     int a;
 9     const int  b;
10 };
11 
12 int main()
13 {
14     A a;
15     A*b(&a);
16     A &c(a);
17     return 0;
18 }

  A *(&a) 和 A &c(a)都没有产生新的对象,所以都没有在调用构造函数,输出结果为:A

  可通过构造函数对成员变量进行初始化

子父类的构造与析构

 

 1 #include <iostream>
 2 using namespace std;
 3 
 4 class A{
 5 public:
 6     A(){cout<<"A"<<endl;}
 7     virtual ~A(){cout << "~A" <<endl;}
 8 };
 9 
10 class B{
11 public:
12     B(){cout << "B" <<endl;}
13     virtual ~B(){cout << "~B" << endl;}
14 };
15 
16 class C : public A{
17 public:
18     C(){cout << "C" << endl;}
19     virtual ~C(){cout << "~C" <<endl;}
20 private:
21     B b;
22 };
23 
24 int main()
25 {
26     C c;
27     return 0;
28 }

 

输出结果为:

1 A
2 B
3 C
4 ~C
5 ~B
6 ~A

  父类的构造函数:

  (1)如果某个类具有基类,执行基类的默认构造函数。除非在ctor-initializer中调用了基类构造函数,此时调用这个构造函数,而不是默认构造函数

  (2)类的非静态数据成员按照声明的顺序创建

  (3)执行该类的构造函数

  父类的析勾函数:

  (1)调用类的析构函数

  (2)销毁类的数据成员,与创建顺序相反

  (3)如果有父类,调用父类的析构函数

  注意所有的析构函数都是virtual。如果前面的析构函数没有声明为virtual,代码也可以继续运行。然而,如果代码使用delete删除一个实际指向派生类的基类指针,析构函数调用链将被破坏。如下:

  

 1 #include <iostream>
 2 using namespace std;
 3 
 4 class A{
 5 public:
 6     A(){cout<<"A"<<endl;}
 7     ~A(){cout << "~A" <<endl;}
 8 };
 9 
10 
11 class C : public A{
12 public:
13     C(){cout << "C" << endl;}
14     ~C(){cout << "~C" <<endl;}
15 };
16 
17 int main()
18 {
19     A *c = new C();z
20     delete c;
21     return 0;
22 }

输出结构为:

A
C
~A

 注:当基类代码中显示了没有默认构造函数,相关版本的派生类必须显示地告诉编译器如何调用Super的构造函数,否则代码将无法编译。

 

技术分享
 1 class Super
 2 {
 3 public:
 4    Super(int i);            
 5 };
 6 class Sub : public Super
 7 {
 8 public:
 9     Sub(int i);    
10 };
11 
12 Sub::Sub(int i) : Super(i)
13 {
14 
15 }
View Code

  从派生类向基类传递构造函数的参数很正常,毫无问题,但是无法传递数据成员。因为在调用基类的构造之后才会初始化数据成员。如果将数据成员作为参数传递给父类构造函数,数据成员不会初始化。

   

  父类的析构函数

  析构函数的调用顺序刚好与构造函数相反:

  (1)调用类的析构函数

  (2)销毁类的数据成员,与创建的顺序相反

  (3)如果有父类,调用父类的析构函数

  注意:所有的析构函数都是virtual。根据经验,所有析构函数都应该声明为virtual。如果前面的析构函数没有声明为virtual,代码也可以继续运行。然而,如果代码使用delete删除一个实际指向派生类的基类指针,析构函数调用链将被破坏。

  从技术角度看,将基类的析构函数声明为virtual,可以纠正上面的问题。派生类将自动“虚化”。然而,建议显示地将所有析构函数声明为virtual

  

 

详谈c++的构造和析构