五十一、通过定义类为final来阻止继承
有时我们会定义这样一种类,我们不希望其他类继承它,或者不想考虑它是否适合作为一个基类。为了实现这一目的,C++11新标准提供了一种防止继承的方法,即在类名后面跟一个关键字final:class NoDerived final {/**/}; //NoDerived不能作为基类
五十二、虚函数的override和final指示符
在c++11中我们可以使用override关键字来说明派生类中的虚函数。这么做的好处是在使得程序员的意图更加清晰的同时让编译器可以为我们发现一些错误,后者在编程实践中显得更加重要。如果我们使用override标记了某个函数,但该函数并没有覆盖已存在的函数,此时编译器将报错:
struct B{
virtual void f1(int) const;
virtual void f2();
void f3();
};
sttuct D1 : B{
void f1(int) const override; //正确:f1与基类中的f1匹配
void f2(int) override; //错误:B没有形如f2(int)的函数
void f3() override; //错误:f3不是虚函数
void f4() override; //错误:B没有名为f4的函数
}
五十三、继承的构造函数
在c++11新标准中,派生类能够重用其直接基类定义的构造函数。一个类只初始化它的直接基类,出于同样的原因,一个类也只继承其直接基类的构造函数。类不能继承默认、拷贝和移动构造函数。如果派生类没有直接定义这些构造函数,则编译器将为派生类合成它们。
派生类继承基类构造函数的方式是提供一条注明了(直接)基类名的using声明语句。举个例子,我们可以重新定义Bulk_quote类,令其继承Dsic_quote类的构造函数:
class Bulk_quote : public Dsic_quote{
public:
using Dsic_quote::Disc_quote; //继承Dsic_quote的构造函数
double net_price(std::size_t) const;
};
通常情况下,using声明语句只是令某个名字在当前作用域内可见。而当作用域构造函数时,using声明语句将令编译器产生代码。对于基类的每个构造函数,编译器都生成一个与之对应的派生类构造函数。换句话说,对于基类的每个构造函数,编译器都在派生类中生成一个形参列表完全相同的构造函数。
五十四、有作用域的enum
C++包含两种枚举:限定作用域的和不限定作用域的。C++11新标准引入了限定作用域的枚举类型。定义限定作用域的枚举类型的一般形式是:首先是关键字enum class(或者等价地使用enum struct)随后是枚举类型的名字以及花括号括起来的枚举类型:enum class open_modes{input, output, append};
定义不限定作用域的枚举类型时省略掉关键字class(或struct),枚举类型的名字是可选的:
enum color{red, yellow, green}; //不限定作用域的枚举类型
//未命名的,不限作用域的枚举类型
enum {floatPrc = 6, doublePrc = 10, double_doublePrc = 16};
如果enum是未命名的,则我们只能在定义该enum的时候定义它的对象