分类: c/c++进行时 2012-04-11 10:02 14697人阅读 评论(7) 收藏 举报
c++stringinitializationclass编译器面试

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. class Base
  4. {
  5. private:
  6. int i;
  7. public:
  8. Base(int x)
  9. {
  10. i = x;
  11. }
  12. };
  13. class Derived : public Base
  14. {
  15. private:
  16. int i;
  17. public:
  18. Derived(int x, int y)
  19. {
  20. i = x;
  21. }
  22. void print()
  23. {
  24. cout << i + Base::i << endl;
  25. }
  26. };
  27. int main()
  28. {
  29. Derived A(2,3);
  30. A.print();
  31. return 0;
  32. }

首先,是访问权限问题,子类中直接访问Base::i是不允许的,应该将父类的改为protected或者public(最好用protected)

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

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

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

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. class Base
  4. {
  5. public:
  6. Base(int i) : m_j(i), m_i(m_j) {}
  7. Base() : m_j(0), m_i(m_j) {}
  8. int get_i() const
  9. {
  10. return m_i;
  11. }
  12. int get_j() const
  13. {
  14. return m_j;
  15. }
  16. private:
  17. int m_i;
  18. int m_j;
  19. };
  20. int main()
  21. {
  22. Base obj(98);
  23. cout << obj.get_i() << endl << obj.get_j() << endl;
  24. return 0;
  25. }

输出为一个随机数和98,为什么呢?因为对于初始化列表而言,对成员变量的初始化,是严格按照声明次序,而不是在初始化列表中的顺序进行初始化,如果改为赋值初始化则不会出现这个问题,当然,为了使用初始化列表,还是严格注意声明顺序吧,比如先声明数组大小,再声明数组这样。

总结完毕,望有用

C++类成员的初始化相关推荐

  1. java类成员变量初始化_探讨Java类中成员变量的初始化方式

    在 Java 里定义一个类的时候,很多时候我们需要提供成员变量,成员变量专业叫法是 Memeber Variable 或者干脆的叫作 Field. 根据是否使用 static 关键字修饰,可以将 Fi ...

  2. 类成员初始化顺序php,PHP-php类成员变量初始化的问题?

    PHP类中,若要初始化成员属性,那么成员属性的初始值必须是一个常数,如果不是常数(如变量),则会报错,所以,如果你要初始化就只能是在构造函数里进行初始化,不过你可以写一个方法,这样就可以在构造函数里批 ...

  3. C++类成员的初始化顺序

    C++中变量的初始化顺序应该是: 1 基类的静态变量或全局变量 2 派生类的静态变量或全局变量 3 基类的成员变量 4 派生类的成员变量 注意,对于一个类中的变量,初始化的顺序并不是按照初始化成员列表 ...

  4. 吐槽C++:C++ 类成员变量初始化 之 初始化带有参数的构造函数 的类成员变量。...

    本来我想写这样的代码: class MatchManager{ public:MatchManager(){}class OnTimerRunFuncHelper{public:OnTimerRunF ...

  5. 关于初始化C++类成员

    转自:http://www.vckbase.com/document/viewdoc/?id=584 在使用C++编程的过程当中,常常需要对类成员进行初始化,通常的方法有两种: 第一种方法: CMYC ...

  6. c++类成员初始化方式

    转载自: https://blog.csdn.net/coder_xia/article/details/7447822 常用的初始化可能如下: 1)赋值初始化 class Student { pub ...

  7. 【Kotlin】Kotlin enum 枚举类 ( 常用用法 | 初始化成员变量 | 实现抽象方法 | 实现接口 | 获取名称和位置索引 | 调用枚举常量方法 )

    文章目录 I . 枚举类常用用法 II . 枚举类初始化 III. 枚举类匿名类 IV . 枚举类实现接口 V . 获取枚举常量名称和位置索引 VI . 获取枚举常量的成员变量 VII . 调用枚举常 ...

  8. 初始化列表||类对象作为类成员|| 静态成员

    初始化列表 作用: C++提供了初始化列表语法,用来初始化属性 语法:构造函数():属性1(值1),属性2(值2)... {} #include <iostream> using name ...

  9. 【转】Java类成员变量默认初始化规则

    一个变量作为类成员使用的时候,如果没有被初始化,java会为其分配默认值: -------------------------------------------------------------- ...

最新文章

  1. 数据库期末复习样卷,临时抱佛脚高分通过考试
  2. mysql报错无效默认值1067_Mysql 报错:#1067 - Invalid default value for 'update_time
  3. 安卓APP_ 布局(1)—— LinearLayout
  4. 公司培训文档-JavaScript[对象.属性]集锦
  5. python基本知识、数据库、网络、编程等总结
  6. linux命令行 基础,Linux命令行基础,关于Bash需要知道的一些常识
  7. python数据分析的发展前景_Python+BI分析5000条招聘数据,原来数据分析工作在这儿最好找...
  8. OpenGL学习笔记_图形渲染管线及典型渲染流程(绘制一个三角形)
  9. 将MNIST数据集转化为png文件
  10. Java获取resin端口_线上解决Resin服务响应过慢的几个方法
  11. 如何反编译dll文件
  12. shufflenet_v1
  13. ppt 母板 如何修改你的背景图片
  14. python逐步回归筛选变量_SPSS进行逐步回归分析
  15. 揭秘中国球员十大豪宅
  16. HASH JOIN ,MERGE JOIN ,NESTED LOOP用法效率比较
  17. 如何让你的“笨兔”更像苹果?
  18. 赛门铁克、思科、FireEye、微软等公司联手对抗Hidden Lynx组织
  19. 超简化版HBASE图书管理系统
  20. 【光链路分析四】OTDR文件解读接口二次开发说明

热门文章

  1. 2021的第二封拒信,来自斯坦福电气工程
  2. 哥伦比亚大学计算机工程面试题
  3. 快速编辑 Shell 命令行
  4. unbuntu 的更新源
  5. Kali Linux Aircrack-ng简单破解WEP加密方式网络
  6. c++11 常量表达式
  7. 总结:数组名和指针完全是两码事
  8. 分支机构L2L *** 到总部再PAT通过专线到合作伙伴(SVTI建立***)
  9. 快速撑握C#知识点之变量,类型及类型转换
  10. poj 2355(简单dp)