类的构造函数

关于类的一篇很好的博客:http://blog.sciencenet.cn/blog-268489-590308.html




类构造函数初始化:概念上有两次

1.初始化列表:这是真正意义上的初始化;有两种情况必须在初始化列表中初始化:

成员类型是没有默认构造函数的类。若没有提供显示初始化式,则编译器隐式使用成员类型的默认构造函数,若类没有默认构造函数,则编译器尝试使用默认构造函数将会失败。

const成员引用类型的成员。因为const对象或引用类型只能初始化,不能对他们赋值。

2.在构造函数体中:其实是在初始化列表初始化后在此赋值;

1.内置数据类型,复合类型(指针,引用)
    在成员初始化列表和构造函数体内进行,在性能和结果上都是一样的
2.用户定义类型(类类型)
    
结果上相同,但是性能上存在很大的差别。因为类类型的数据成员对象在进入函数体前已经构造完成,也就是说在成员初始化列表处进行构造对象的工作,调用构造函数,在进入函数体之后,进行的是对已经构造好的类对象的赋值,又调用个拷贝赋值操作符才能完成(如果并未提供,则使用编译器提供的默认按成员赋值行为)



1.对于任意一个类,如果没有定义任何构造函数和析构函数,则由编译器自动的产生4个缺省的函数:

默认构造函数:A(void); // 缺省的无参数构造函数

默认拷贝构造函数:A(const A &a); // 缺省的拷贝构造函数
默认析构函数:~A(void)//缺省的析构函数

默认的赋值函数:A & operate =(const A &a); // 缺省的赋值函数


析构函数表示清除此对象,默认拷贝构造函数和默认的赋值函数只是浅复制;

一旦类中定义了,编译器就不会再默认创建;


 2. 构造函数和拷贝构造函数的区别

构造函数:初始化类的成员参数

拷贝构造函数:用一个类初始化另一个类(Test(Test &c_t)是自定义的拷贝构造函数,拷贝构造函数的名称必须与类名称一致,函数的形式参数是本类型的一个引用变量,且必须是引用

拷贝构造函数被调用的情况:

一个对象以值传递的方式传入函数体
一个对象以值传递的方式从函数返回
一个对象需要通过另外一个对象进行初始化。


3.深拷贝,浅拷贝

如果一个类拥有资源,当这个类的对象发生复制过程的时候,资源重新分配,这个过程就是深拷贝,反之,没有重新分配资源,就是浅拷贝

缺省的拷贝构造函数就是浅拷贝,也称位拷贝:没有拷贝内容,仅仅拷贝了地址。

深拷贝的例子:

#include <iostream>
 using namespace std;
 class CA
 {
 public:
  CA(int b,char* cstr)
  {
   a=b;
   str=new char[b];
   strcpy(str,cstr);
  }
  CA(const CA& C)
  {
   a=C.a;
   str=new char[a]; //深拷贝
    if(str!=0)
    strcpy(str,C.str);
  }
  void Show()
  {
   cout<<str<<endl;
  }
  ~CA()
  {
   delete str;
  }
 private:
  int a;
  char *str;
 };

int main()
 {
 CA A(10,"Hello!");
 CA B=A;
 B.Show();
 return 0;
 } 

4. 位拷贝和值拷贝

A.m_data和B.m_data分别指向一段区域,A.m_data="windows",B.m_data=“linux";

如果未重写赋值函数,将B赋给A;编译器会默认进行位拷贝,A.m_data=B.m_data

则A.m_data和B.m_data指向同一块区域,虽然A.m_data指向的内容会改变成"linux",但是这样容易出现这些问题:

(1):A.m_data原来指向的内存区域未释放,造成内存泄露。

(2):A.m_dataB.m_data指向同一块区域,任何一方改变都会影响另一方

 (3):当对象被析构时,B.m_data被释放两次。


5. 组合和继承类的初始化顺序,析构顺序

(1)构造顺序:

从类层次的最根处开始,而在每一层都会调用基类的构造函数

然后调用成员对象构造函数,成员函数的构造顺序与初始化列表无关,而与定义的顺序有关

(2)析构顺序

与构造顺序完全相反


构造函数的三个作用:
分配空间
成员初始化
执行初始化函数体

子类构造函数必须对父类进行初始化,否则出错;
父类有默认构造函数时可以不显式的初始化

编译器会合成默认构造函数的情况
①组合,且组合成员含有默认构造函数
②继承自一个有默认构造函数的类
③类中有虚函数


当一个类中既有继承又有组合时,其构造函数列表

①必须对基类初始化,否则编译出错!当基类含有默认构造函数时,不必显式的初始化;若基类没有默认构造函数,则必须在初始化列表中显式的初始化;若基类和派生类均无任何 自定义构造函数,编译器为二者合成默认构造函数并初始化为随机值(有些编译器运行时会报错,如VS2010)(此时为无用构造函数)
②组合,不必再初始化列表中初始化,但是使用的时候会调用其构造函数初始化,不在初始化列表中初始化编译不会出错!组合和普通的类定义一样,会调用相应的构造函数初始化!A中含有B,若组合的对象B含有默认构造函数,则编译器为A合成默认构造函数,其调用B的默认构造函数;若组合的类中无默认构造函数,则要调用相应的构造函数初始化,若仍然使用缺省的则报错:没有合适的缺省构造函数!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值