不时会留意到有人问起如何阻止 C++ 中的类被继承,但多数人都没有把这个问题问对。
在 C++11 标准之前,阻止类被继承在语法上是做不到的,大家通常做到的只是继承而来的类不能被实例化了。这样一来,继承得到的类就完全没有用了。虽然最终的效果一致,但对问题的理解其实是有差异的。
从 C++11 标准开始,C++ 引入了一个新的关键字 final,只有被 final 修饰的类才能真正做到不能被继承。
下面举例实现常用的以达到“不能被继承/继承类不能被实例化”的几种手段。
私有化构造函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Demo1
{
public:
    static Demo1* Create()
    {
        return new Demo1;
    }
private:
    // 注意:私有掉构造函数
    Demo1() {}
    Demo1(const Demo1&);
    void operator=(const Demo1&);
};
class Test1 : public Demo1
{
};
int main()
{
//  Demo1*      pd1 = new Demo1;        // 错误:不能调用私有构造
    Demo1*      pd1 = Demo1::Create();
//  Test1*      pt1 = new Test1;        // 错误:不能调用基类私有构造
}
使用 虚继承 + 私有基类构造函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
template<typename T>
class SealedT
{
    // 注意:不是 friend class T;
    friend T;
private:
    SealedT() {}
};
// 注意:是虚继承
class Demo2 : virtual SealedT<Demo2>
{
};
int main()
{
    Demo2*      pd2 = new Demo2;
//  Test2*      pt2 = new Test2;        // 错误:不能访问间接虚基类
}  
使用 虚继承 + 受保护的基类构造函数
这个其实与前面一种形式是类似的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Sealed
{
protected:
    Sealed() {}
};
class Demo3 : virtual Sealed
{
};
class Test3 : public Demo3
{
};
int main()
{
    Demo3*      pb3 = new Demo3;
//  Test3*      pt3 = new Test3;        // 错误:不能访问间接虚基类
}  
使用 final 关键字
这个是最简单、最直接、最完美的。C++ 标准为啥如此晚才推出此功能。
1
2
3
4
5
6
7
8
9
10
11
12
13
class Demo4 final
{
};
// 不能从被 final 修饰的类继承,编译失败
/*
class Test4 : public Demo4
{
};
*/  
