C++ 最终类和切片习惯用法

5 c++ final object-slicing

我碰巧正在浏览 mongoDB 的源代码,发现了这个有趣的构造:

class NonspecificAssertionException final : public AssertionException {
public:
    using AssertionException::AssertionException;

private:
    void defineOnlyInFinalSubclassToPreventSlicing() final {}
};
Run Code Online (Sandbox Code Playgroud)

私有方法如何防止切片?我似乎想不出问题所在。

干杯,乔治

Sto*_*ica 4

唯一final可以应用说明符的成员函数是虚拟成员函数。很可能在AssertionException它自己的基类中或其一个基类中,该成员被定义为

virtual void defineOnlyInFinalSubclassToPreventSlicing() = 0;
Run Code Online (Sandbox Code Playgroud)

因此,层次结构中的所有类(除了最派生的类)都是抽象基类。人们不能创建抽象类的值(它们只能作为基础)。因此,人们可能不会一不小心写下

try {
    foo();
}
catch(AssertionException const e) { // oops catching by value
} 
Run Code Online (Sandbox Code Playgroud)

如果AssertionException不是抽象的话,上面的内容也可以写出来。但是当它是抽象的时,编译器会向异常处理程序抱怨,迫使我们通过引用捕获。推荐的做法是通过参考进行捕捉。

将成员(和类)标记为final确保不可能进一步派生。因此,当继承层次结构发生更改时,该问题不会意外再次出现。因为添加另一个类并再次定义为 Final 的程序员defineOnlyInFinalSubclassToPreventSlicing将引发编译器的错误,因为该成员已在基类中声明为 Final。因此,他们必须从基类中删除实现,从而使其再次抽象。

这是一个簿记系统。