第三章 《类和对象II》

目录

1.什么是常对象?使用常对象时要注意什么?

2.什么是常数据成员?常数据成员怎么赋初值?

3.带成员初始化列表的构造函数的执行顺序是怎样的?

4.在构造函数成员初始化列表中初始化数据成员和在构造函数体中初始化,结果是一样的?二者在性能方面有什么区别呢?

5.什么是常成员函数?使用常成员函数要注意什么?

6.mutable有什么作用?

7.C++中的explicit的作用是什么?

8.什么是子对象?

9.子对象的构造函数的执行次序是什么样的?

10.子对象的析构函数的执行次序是什么样的?

11.什么是静态子对象?

12.什么是前向引用声明?

13.说明C++中局部类和嵌套类的区别。

14.说明嵌套类的主要作用。

15.在软件开发中有一种单例模式,即在应用中仅允许创建类的一个实例。那么如何采用C++实现单例模式?


1.什么是常对象?使用常对象时要注意什么?

常对象是指对象常量。定义格式:“类名 const 对象名;”或者“const 类名 对象名;”

使用常对象时要注意:

在定义常对象时必须进行初始化;

常对象的数据成员不能被更新;

如果一个对象被定义为常对象,则不能调用该对象的非const成员函数,否则会报错。这样做是为了防止非const成员函数修改常对象中的数据元素值,因为const成员函数是不可以修改对象中的数据成员值的。


2.什么是常数据成员?常数据成员怎么赋初值?

在类中使用const定义的数据成员是常数据成员。

常数据成员的赋初值只能通过构造函数,并且构造函数只能通过成员初始化列表来实现。


3.带成员初始化列表的构造函数的执行顺序是怎样的?

先执行初始化列表,再执行函数体,对于含有多个初始化项的列表不是按照从左到右或者右到左的顺序执行,而是按照数据成员在类中定义的顺序执行的。


4.在构造函数成员初始化列表中初始化数据成员和在构造函数体中初始化,结果是一样的?二者在性能方面有什么区别呢?

参考:构造函数初始化的方法及区别

对于类的非const数据成员,可以在成员初始化列表中初始化,也可以在构造函数体中初始化,二者的结果是一样的。

一般情况下,对于内置的数据类型(含指针和引用),在成员初始化列表和构造函数体内进行,在性能和结果上都是一样的;

对于用户自定义的类类型(即子对象的情况),在性能上存在很大差别,因为前者只用调用一次构造函数,后者除了调用一次默认的构造函数,还要调用赋值运算符才能完成。而函数调用时浪费资源的,所以在这种情况下采用成员初始化列表来初始化数据成员性能更优。


5.什么是常成员函数?使用常成员函数要注意什么?

使用const关键字声明的函数为常成员函数,声明格式为“函数类型 函数名(参数表) const;

在使用常成员函数是要注意:

const是函数类型的一个组成部分,因此在实现部分也要带const关键字;

常成员函数不能更新对象的数据成员,也不能调用该类中的非常成员函数;

如果将一个对象定义为常对象,则通过该常对象只能调用它的常成员函数,不能调用非const成员函数;

const关键字可以参与区分重载函数。如“void display();”和“void display() const;”是对display的有效重载。


6.mutable有什么作用?

在定义一个常对象后只能调用const成员函数,而且const成员函数不能修改数据成员值。

如果希望通过常对象修改某些数据成员值,只需将其定义为mutable(易变的),mutable数据成员永远不会是const成员,即使它是一个const对象的数据成员。

const成员函数可以修改mutable数据成员的值,常对象通过调用该const成员函数即可修改该mutable数据成员的值。


7.C++中的explicit的作用是什么?

C++中的explicit关键字(含义是明确的,不隐瞒的)只能用于修饰只有一个参数的类构造函数,它的作用是表示该构造函数时显式的,而非隐式的,从而阻止不允许的经过构造函数进行的隐式转换。类构造函数在默认情况下都是隐式的。

在C++中一个参数的构造函数(或者除了第一个参数外其余参数都有默认值的多参构造函数)承担了两个角色:一是构造器,二是默认且隐含的类型转换操作符。所以在写形如A a=n;这样的代码且恰好类A有单个参数的构造函数时编译器自动调用这个构造函数创建一个类A的对象a。

explicit不是重载区分符。一个函数加和不加explicit修饰,不构成重载函数。


8.什么是子对象?

当一个类的数据成员是另一个类的对象时,这个对象称为子对象。


9.子对象的构造函数的执行次序是什么样的?

当子对象B含有构造函数,则只能在含有对象B的类A的构造函数的成员初始化列表中进行初始化;如果子对象B不含构造函数,则对象B还可以在类A的构造函数体中初始化。

对象成员构造函数的调用顺序取决于这些子对象成员在类中的定义顺序,而与它们在成员初始化表中的位置无关。

在建立类对象时先调用各个对象成员的构造函数,初始化相应的子对象成员,然后才执行类的构造函数体,初始化本类中的其他数据成员。


10.子对象的析构函数的执行次序是什么样的?

析构函数的执行次序是先执行函数体,再以子对象在类A中定义的相反次序调用各类的析构函数。


11.什么是静态子对象?

在一个类中可以定义另外一个类的静态子对象,静态子对象需要在类外初始化。初始化格式为“子对象类名 所属类::静态子对象名[(参数表)]”

静态子对象属于类对象,和int等类型的静态数据成员类似,只是在销毁时要调用析构函数。


12.什么是前向引用声明?

C++中的类通常是先声明再使用。有时会遇到两个类相互引用的情况,这时必然有一个类在声明之前就被使用。解决这个问题的方法是使用前向引用声明。

前向引用声明是在引用未声明的类之前对该类进行预声明,它只是为程序引入一个代表该类的标识符,类的具体声明可以在程序的其他地方。

前向引用声明仅引入一个代表类的标识符,在没有遇到该类标识符的实际声明之前不能使用该类的任何成员。

例如:类A声明在前,类B声明在后。但类A的成员函数引用了B的对象和成员函数。这时,要对类B进行前向引用声明。并且类A中引用类B对象的成员函数的实现必须放在类B的声明之后,否则会出现不能识别类B的错误。


13.说明C++中局部类和嵌套类的区别。

在一个函数体内定义的类称为局部类。在局部类中只能使用它的外围作用域中的对象和函数进行联系,因为外围作用域中的变量与该局部类的对象无关。局部类的所有成员都必须定义在类体内,并且局部类不能包含静态成员。

在一个类中声明的类称为嵌套类,从作用域的角度看,嵌套类被隐藏在外围类之中,该类名只能在外围类中使用,如果在外围类的作用域外使用该类名,需要加名字限定。从访问权限的角度来看,嵌套类名与他的外围类的对象成员名具有相同的访问权限规则。不能访问嵌套类的对象中的私有成员函数,也不能对外围类的私有嵌套类建立对象。嵌套类的成员函数可以在它的类体外定义。


14.说明嵌套类的主要作用。

定义嵌套类的作用在于隐藏类名,减少全局的标识符,从而限制用户能否使用该类建立对象,这样可以提高类的抽象能力,并且强调了两个类(外围类和嵌套类)之间的主从关系。


15.在软件开发中有一种单例模式,即在应用中仅允许创建类的一个实例。那么如何采用C++实现单例模式?

略,以后补充,见P112。


参考:《直击招聘 程序员面试笔试 C++语言深度解析》李春葆、李筱池 主编

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值