story of 构造函数

一般我们进行成员变量初始化用两种方法
第一种是通过在构造函数内赋值
class Point
{
 public:
 Point(){ _x = 0; _y = 0;};
 Point( int x, int y ){ _x = 0; _y = 0; }
 private:
 int _x, _y;
};
第二种是使用初始化列表
 class Point
{
public:
 Point():_x(0),_y(0){};
 Point( int x, int y ):_x(x),_y(y){}
private:
 int _x, _y;
};
这两种用法是有区别的
一、在有些情况下,必须使用初始化列表。特别是const和引用数据成员被初始化时。
class Point
{
// 这个类的定义就要求使用初始化成员列表,因为const成员只能被初始化,不能被赋值
public:
 Point():_x(0),_y(0){}; 
 Point( int x, int y ):_x(x),_y(y){}
 //Point(){ _x = 0; _y = 0;}
 //Point( int x, int y ){ _x = 0; _y = 0; }
private:
 const int _x, _y;
};
二、是从效率方面来说的,对于内置类型或复合类型,差异不会太大,但对于非内置数据类型,差异还是很明显的
如我们再给Point类添加一个新的string类型的成员变量
class Point
{
 const int _x, _y;
 string _name;
};
构造函数内赋值进行初始化
Point( int x, int y, string name ){ _x = 0; _y = 0; _name = name; }
_name = name 这个表达式会调用string类的缺省构造函数一次,再调用Operator=函数进行赋值一次。所以需调用两次函数:一次构造,一次赋值
用初始化列表进行初始化
Point( int x, int y, string name ):_x(x),_y(y), _name(name){}  
_name会通过拷贝构造函数仅以一个函数调用的代码完成初始化
即使是一个很简单的string类型,不必要的函数调用也会造成很高的代价。随着类越来越大,越来越复杂,它们的构造函数也越来越大而复杂,那么对象创建的代价也越来越高,所以一般情况下建议使用初始化列表进行初始化,不但可以满足const和引用成员的初始化要求,还可以避免低效的初始化数据成员。
《C++ Primer》中提到在以下三种情况下需要使用初始化成员列表:

一、需要初始化的数据成员是对象的情况(这里包含了继承情况下,通过显示调用父类的构造函数对父类数据成员进行初始化);
二、需要初始化const修饰的类成员;
三、需要初始化引用成员数据;

即:

例一、数据成员是对象,切对象只有含参数的构造函数;
        如果我们有一个类成员,它本身是一个类或者是一个结构,而且这个成员它只有一个带参数的构造函数,而没有默认构造函数,这时要对这个类成员进行初始化,就必须调用这个类成员的带参数的构造函数,如果没有初始化列表,那么他将无法完成第一步,就会报错。
class Test
{
public:
         Test(int x,int y,int z);
private:
         int a;
         int b;
         int c;
};
class MyTest
{
public:
        MyTest():test(1,2,3){}        //初始化,初始化列表在构造函数执行前执行(这个可以测试,对同一个变量在初始化列表和构造函数中分别初始化,首先执行参数列表,后在函数体内赋值,后者会覆盖前者)。
private:
        Test test;            //声明
};
        因为Test有了显示的带参数的构造函数,那么他是无法依靠编译器生成无参构造函数的,所以没有三个int型数据,就无法创建Test的对象。
        Test类对象是MyTest的成员, 想要初始化这个对象test,那就只能用成员初始化列表,没有其他办法将参数传递给Test类构造函数。
例三、子类初始化父类的私有成员,需要在(并且也只能在)参数初始化列表中显示调用父类的构造函数,如下:
class Test
{
 private:
  int a;
  int b;
  int c;
 public:
  Test(int a,int b,int c)
  {
   this->a = a;
   this->b = b;
   this->c = c;
  }
  int getA(){return a;}
  int getB(){return b;}
  int getC(){return c;}
};
class MyTest:public Test
{
 private:
  int d;
 public:
  MyTest(int a,int b,int c,int d):Test(a,b,c)
  //MyTest(int a,int b,int c,int d)
  { 
      //Test(a,b,c);           //构造函数只能在初始化列表中被显示调用,不能在构造函数内部被显示调用
   this->d = d;
  }
  int getD(){return d;}
}; 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值