C++类成员的初始化

来源:互联网 发布:串口调试软件下载 编辑:程序博客网 时间:2024/05/29 15:11

本文转自http://blog.csdn.net/coder_xia/article/details/7447822

1、关于构造函数

1)用构造函数确保初始化

对于一个空类

[cpp] view plaincopy
  1. class Empty { };  
编译器会自动声明4个默认函数:构造函数,拷贝构造函数,赋值函数,析构函数(当然,如果不想使用自动生成的函数,就应该明确拒绝),这些生成的函数都是public且inline。构造函数对数据成员进行初始化,使用未初始化值可能导致无法预知的错误,所以,确保每一个构造函数都将每一个成员初始化。

2)为什么构造函数不能有返回值

如果有返回值,要么编译器必须知道怎么处理返回值,要么就客户程序员显式调用构造函数和析构函数,这样,还有安全性么?

3)为什么构造函数不能为虚函数

简单来说,虚函数调用的机制,是知道接口而不知道其准确对象类型的函数,但是创建一个对象,必须知道对象的准确类型;当一个构造函数被调用时,它做的首要事情之一就是初始化它的VPTR来指向VTABLE。

4)构造函数的一个面试题:

[cpp] view plaincopy
  1. #include <iostream>  
  2. using namespace std;  
  3.   
  4. class Base   
  5. {  
  6. private:  
  7.     int i;  
  8. public:  
  9.     Base(int x)  
  10.     {  
  11.         i = x;  
  12.     }  
  13. };  
  14.   
  15. class Derived : public Base  
  16. {  
  17. private:  
  18.     int i;  
  19. public:  
  20.     Derived(int x, int y)  
  21.     {  
  22.         i = x;  
  23.     }  
  24.     void print()  
  25.     {  
  26.         cout << i + Base::i << endl;  
  27.     }  
  28. };  
  29.   
  30. int main()  
  31. {  
  32.     Derived A(2,3);  
  33.     A.print();  
  34.     return 0;  
  35. }  
首先,是访问权限问题,子类中直接访问Base::i是不允许的,应该将父类的改为protected或者public(最好用protected)

其次,统计父类和子类i的和,但是通过子类构造函数没有对父类变量进行初始化;此处编译会找不到构造函数,因为子类调用构造函数会先找父类构造函数,但是没有2个参数的,所以可以在初始化列表中调用父类构造函数

最后个问题,是单参数的构造函数,可能存在隐式转换的问题,因为单参数构造函数,和拷贝构造函数形式类似,调用时很可能会发生隐式转换,应加上explicit关键字,修改后如下(程序员面试宝典上只改了前2个)

[cpp] view plaincopy
  1. #include <iostream>  
  2. using namespace std;  
  3.   
  4. class Base   
  5. {  
  6. protected:  
  7.     int i;  
  8. public:  
  9.     explicit Base(int x)  
  10.     {  
  11.         i = x;  
  12.     }  
  13. };  
  14.   
  15. class Derived : public Base  
  16. {  
  17. private:  
  18.     int i;  
  19. public:  
  20.     Derived(int x, int y):Base(x)  
  21.     {  
  22.         i = y;  
  23.     }  
  24.     void print()  
  25.     {  
  26.         cout << i + Base::i << endl;  
  27.     }  
  28. };  
  29.   
  30. int main()  
  31. {  
  32.     Derived A(2,3);  
  33.     A.print();  
  34.     return 0;  
  35. }  

2、初始化列表

1)使用初始化列表提高效率

常用的初始化可能如下:

[cpp] view plaincopy
  1. class Student   
  2. {  
  3. public:  
  4.     Student(string in_name, int in_age)  
  5.     {  
  6.         name = in_name;  
  7.         age = in_age;  
  8.     }  
  9. private :  
  10.     string name;  
  11.     int    age;  
  12. };  
    以前楼主也习惯这么写,可以达到预期效果,不过不是最佳做法,因为在构造函数中,是对name进行赋值,不是初始化,而string对象会先调用它的默认构造函数,再调用string类(貌似是basic_string类)的赋值构造函数;对于上例的age,因为int是内置类型,应该是赋值的时候获得了初值。

    要对成员进行初始化,而不是赋值,可以采用初始化列表(member initialization list)改写为如下:

[cpp] view plaincopy
  1. class Student   
  2. {  
  3. public:  
  4.     Student(string in_name, int in_age):name(in_name),age(in_age) {}  
  5. private :  
  6.     string name;  
  7.     int    age;  
  8. };  
    结果与上例相同,不过在初始化的时候调用的是string的拷贝构造函数,而上例会调用两次构造函数,从性能上会有不小提升

    有的情况下,是必须使用初始化列表进行初始化的:const对象、引用对象

2)初始化列表初始顺序

考虑以下代码:

[cpp] view plaincopy
  1. #include <iostream>  
  2. using namespace std;  
  3.   
  4. class Base   
  5. {  
  6. public:  
  7.     Base(int i) : m_j(i), m_i(m_j) {}  
  8.     Base() : m_j(0), m_i(m_j) {}  
  9.     int get_i() const  
  10.     {  
  11.         return m_i;  
  12.     }  
  13.     int get_j() const  
  14.     {  
  15.         return m_j;  
  16.     }  
  17.   
  18. private:  
  19.     int m_i;  
  20.     int m_j;  
  21.   
  22. };  
  23.   
  24. int main()  
  25. {  
  26.     Base obj(98);  
  27.     cout << obj.get_i() << endl << obj.get_j() << endl;  
  28.     return 0;  
  29. }  
     
输出为一个随机数和98,为什么呢?因为对于初始化列表而言,对成员变量的初始化,是严格按照声明次序,而不是在初始化列表中的顺序进行初始化,如果改为赋值初始化则不会出现这个问题,当然,为了使用初始化列表,还是严格注意声明顺序吧,比如先声明数组大小,再声明数组这样。
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 面试时没有正装怎么办 宝宝喝了沐浴露怎么办 开实体童装店没人买怎么办 宝宝一岁半了还不会说话怎么办 十个月宝宝不吃辅食怎么办 八个月宝宝不吃米糊怎么办 八个月宝宝不吃辅食怎么办 六个月宝宝不吃米粉怎么办 4个月婴儿积食怎么办 黑色的衣服泛红怎么办 不听劝的人该怎么办 牛仔裙子腰大了怎么办 天猫店铺降权怎么办 淘宝做文胸的标题要怎么办 秋衣弹力衣服松了怎么办 假离婚变成真的怎么办 百家利钱不到账怎么办 皮鞋撑大了怎么办变小 鞋穿着走路掉跟怎么办 浅口帆布鞋大了怎么办 布鞋后鞋跟老掉怎么办 穿坡跟凉鞋容易打滑摔倒怎么办 运动鞋烂了个口怎么办 运动鞋的网烂了怎么办 运动鞋鞋一个一个高一个低怎么办 淘宝预售水果不发货怎么办 淘宝评价忘记晒图了怎么办 参加水果展没有实物怎么办 没做过运营面试怎么办 苹果5s16g内存满了怎么办 618天猫有活动淘宝没有怎么办 天猫国际买到假货怎么办 天猫恶意差评怎么办 天猫删除差评被扣分了怎么办 天猫收到差评怎么办 天猫给差评骚扰怎么办 天猫客户差评怎么办 天猫没法给差评怎么办 天猫上限购一件怎么办 拍下商品不发货怎么办 天猫红包过期了怎么办