1. 纯虚函数的定义和用法
C++中的虚函数是一种特殊的函数,其指针可以在运行时动态绑定到具体的函数实现。虚函数的函数体可以为空,这种函数被称为“纯虚函数”。
1.1 纯虚函数的定义
在C++中,我们可以通过将虚函数的函数体设为0来定义纯虚函数。定义一个纯虚函数可以使其子类必须实现该函数,否则这些子类会被编译器认为是抽象类。
class Base {
public:
virtual void func() = 0; // 纯虚函数
};
class Derived : public Base {
public:
void func() { std::cout << "Derived func" << std::endl; }
};
在上面的代码中,Base类中的虚函数func被定义为纯虚函数。Derived类继承自Base类,并实现了该纯虚函数。这样,Derived类就不再是抽象类。
1.2 纯虚析构函数的定义
纯虚析构函数在C++中还有一个特殊的作用,可以用于定义抽象基类。我们可以通过在析构函数前加上关键字virtual且函数体设为0来定义纯虚析构函数。
class Base {
public:
virtual ~Base() = 0; // 纯虚析构函数
};
Base::~Base() {} // 纯虚析构函数的定义
在上面的代码中,Base类中的析构函数被定义为纯虚析构函数。由于删除一个指向抽象基类的指针时必须先删除它所指向的派生类对象,因此声明Base的析构函数为纯虚析构函数是很有必要的,这会强制所有的子类必须实现自己的析构函数。
2. final说明符的用法
在C++11中,final说明符被用来指定一个虚函数不能被它的子类重载或覆盖。被指定为final的函数一定是虚函数。
2.1 final的用法
使用final说明符的方式非常简单,只需在函数声明的后面加上关键字final即可。
class Base {
public:
virtual void func1() final { }
virtual void func2() { }
};
class Derived : public Base {
public:
// 错误:无法重载 'virtual void Base::func1() const'
//void func1() const override {}
// 正确:可以重载Base中没有被final标记的虚函数
void func2() { }
};
在上面的示例代码中,Base类中的func1被标记为final,因此它不能被派生类重载或覆盖。Derived类中重新定义func1会导致编译错误。
2.2 final的优点
final指示符还有一个很重要的作用,可以让编译器在编译时对虚函数表做出优化,从而提高程序的运行效率。
假设我们有一个类A,它有一个虚函数func1。如果我们在类A的某个派生类B中重新定义了func1,则编译器将在运行时动态决定调用哪个函数:A中的func1还是B中的func1。这个过程需要根据虚函数表来检查两个函数的地址,是比较耗时的。
但是,如果我们将A中的func1指定为final,则编译器只需要在编译时就确定调用哪一个函数,这样可以避免在运行时动态查找虚函数表,节省了时间和计算资源。
3. 总结
本文介绍了C++11中新增的两个特性:纯虚函数和final说明符。其中,纯虚函数可以用来定义抽象基类,让派生类必须实现该函数;final说明符则指定一个虚函数不能被它的子类重载或覆盖,并可以优化虚函数表的访问速度。
在实际编码中,对纯虚函数和final指示符的使用要结合具体的业务场景和代码实现需求来选择。但是,掌握这些特性的基本用法和优点,可以帮助我们编写更加可维护、高效的C++代码。