09-对类的修改
18.1.7 对类的修改
为简化和扩展类设计,C++11做了多项改进。这包括允许构造函数被继承和彼此调用、更佳的方法访问控制方式以及移动构造函数和移动赋值运算符,这些都将在本章介绍。下面先来复习本书前面介绍过的改进。
1.显式转换运算符
有趣的是,C++很早就支持对象自动转换。但随着编程经验的积累,程序员逐渐认识到,自动类型转换可能导致意外转换的问题。为解决这种问题,C++引入了关键字explicit,以禁止单参数构造函数导致的自动转换:
class Plebe
{
Plebe(int); // automatic int-to-plebe conversion
explicit Plebe(double); // requires explicit use
...
};
...
Plebe a, b;
a = 5; // implicit conversion, call Plebe(5)
b = 0.5; // not allowed
b = Plebe(0.5); // explicit conversion
C++11拓展了explicit的这种用法,使得可对转换函数做类似的处理(参见第11章):
class Plebe
{
...
// conversion functions
operator int() const;
explicit operator double() const;
...
};
...
Plebe a, b;
int n = a; // int-to-Plebe automatic conversion
double x = b; // not allowed
x = double(b); // explicit conversion, allowed
2.类内成员初始化
很多首次使用C++的用户都会问,为何不能在类定义中初始化成员?现在可以这样做了,其语法类似于下面这样:
class Session
{
int mem1 = 10; // in-class initialization
double mem2 {1966.54}; // in-class initialization
short mem3;
public:
Session(){} // #1
Session(short s) : mem3(s) {} // #2
Session(int n, double d, short s) : mem1(n), mem2(d), mem3(s) {} // #3
...
};
可使用等号或大括号版本的初始化,但不能使用圆括号版本的初始化。其结果与给前两个构造函数提供成员初始化列表,并指定mem1和mem2的值相同:
Session() : mem1(10), mem2(1966.54) {}
Session(short s) : mem1(10), mem2(1966.54), mem3(s) {}
通过使用类内初始化,可避免在构造函数中编写重复的代码,从而降低了程序员的工作量、厌倦情绪和出错的机会。
如果构造函数在成员初始化列表中提供了相应的值,这些默认值将被覆盖,因此第三个构造函数覆盖了类内成员初始化。