Modern C++ 新特性 – final修饰符

Modern C++ 新特性— final修饰符

在java语言中,你可以使用final关键字来修饰一个函数,来告诉编译器该函数不能被重载,也可以使用final关键字修饰一个类告诉编译器该类不能被继承。现在C++11之后也引入了final关键字。看下面一个例子:

#include using namespace std;class Base {public:virtual void mfunc() final {cout << "Base::mfunc" << endl;}};class Derived : public Base {void mfunc() {cout << "Derived::mfunc" << endl;}};int main() {Derived d;Base &b = d;b.mfunc();return 0;}

编译上面的代码会得到如下错误:

'Base::mfunc': function declared as 'final' cannot be overridden by 'Derived::mfunc'

原因是基类当中的mfunc被声明为了final,所以编译器不允许子类重载。再看个例子:

#include using namespace std;class Base final {public:virtual void mfunc() {cout << "Base::mfunc" << endl;}};class Derived : public Base {void mfunc() {cout << "Derived::mfunc" << endl;}};int main() {Derived d;Base &b = d;b.mfunc();return 0;}

编译上面的代码会得到如下错误:

'Derived': cannot inherit from 'Base' as it has been declared as 'final'

原因是基类被final修饰,因此编译器不允许子类继承。但是在c++ final却不能被看做一个关键字,因为它只有在上面两种情况下才有意义。比如在下面的代码中final就是一个普通变量。这样做可能是为了向前兼容的原因。

#include using namespace std;int main() {int final = 0;cout << final << endl;return 0;}

那么为什么要用final修饰来让一个类不能被继承呢?

第一,当你设计一个类的时候,有时候可能你不希望使用者继承这个类或者继承这个类可能会带来某些问题,那么你可以用final修饰该类,明确告诉使用者,该类不能被继承,也告诉编译器替你把好关。

第二,一个类使用final修饰后,可以去虚化,从而提高程序性能。看下面的例子:

#include using namespace std;class dog {public:virtual void speak() {cout << "woong.. woong.." << endl;}};int main() {dog good_dog;good_dog.speak();return 0;}

加上final后,编译器就会尝试去除speak的virtual属性,因为你已经明确告诉了它这个类不会被继承,所以保留virtual这个属性已经没有意义,因此编译器会尝试优化。所以,将由在运行时的通过虚函数表间接调用,转为编译时地址确定的直接调用。这样效率就提升了。

本文简单介绍了c++11之后引入的final修饰符,希望对大家有所帮助。