学科分类
目录
C++基础

管理虚方法

通过学习多态的知识,我们已经了解到对于派生类来说很多时候会覆盖它继承的虚函数,覆盖时要求派生类中重新定义函数的返回值类型、函数名、参数与基类虚函数的对应内容一致,否则在派生类中创建新的函数,不能达到覆盖的目的,此时编译并不会报错。若想通过编译器发现这样的错误,C++11新标准中可以使用override关键字来说明派生类中的虚函数,这样就使得覆盖的意图更加清晰,并且也可以借助于编译器检查是否完成了覆盖。使用override的方法是在派生类中虚函数形参列表后添加override关键字。

下列代码描述了声明函数具有override属性的方法,具体内容如下所示:

class Base{                    //定义基类
public:
  virtual void func1(int);          //声明虚函数
   virtual void func2();
  void func3();
};
class Derived:public Base           //定义派生类
{
public:
  void func1(int) override;         //正确,使用override说明覆盖基类同名虚函数
   void func2(float) override;       //错误,函数参数与基类函数不同,不可覆盖
void func3() override;          //错误,不可覆盖非虚函数
};

上述代码中,派生类函数func1()后面的override使用正确,因为它要覆盖的是基类中返回值类型、函数名、参数完全相同的虚函数。func2()后面使用override时,编译器会报错,因为在基类中同名虚函数func2()是无参函数,派生类中的func2()是重定义而不是改写。派生类中的func3()后面使用override也会报错,因为基类中的同名函数不是虚函数。override只可以对虚函数覆盖进行检查。

除了override,C++11新标准还增加了防止基类被继承和防止派生类重写函数的功能。这是由特殊的标识符final来完成的,其方法是在类名后或函数参数后添加关键字final。

下述代码描述了使用final修饰类的方法,内容如下所示:

class NoDerived final             //定义final类,不可作为基类派生新类
{
  …
};
class Base{                  //定义普通类,可作为基类
  …
};
//正确,定义final类Last,不可派生新类,该类派生自Base
class Last final:public Base      
{
  …
};
class Error1:public NoDerived       //错误,不可通过NoDeived类派生新类
{

};
class Error2:public Last         //错误,不可通过Last类派生新类
{
  …
};

从上述代码可以看出,被final修饰的类,不可作为基类派生新类。final除了修饰类外,还可以修饰某个函数。如果已经把函数定义成final,则之后任何尝试覆盖该函数的操作都将发生错误。

下述代码演示了使用final修饰函数的方法,具体内容如下所示:

class Base{                  //基类定义
public:
  virtual void func1(int) final;   //虚函数,不可被覆盖
   virtual void func2();
};
class Derived:public Base         //派生类定义
{
public:
  void func1(int);            //错误,基类中的同名虚函数已定义为final
   void func2() override;       //正确,覆盖基类同名虚函数
};

上述代码中,基类中的虚函数func1()使用final修饰,阻止了派生类重写这个函数。

需要注意的是,override和final都不是C++语言的关键字,它们只是技术上的标识符,只有在类似上述代码中,对类和函数性质进行说明时才有特殊意义,用在其它地方仍然是有效标识符。

点击此处
隐藏目录