C++ final 说明符怎么用?

文章导读
Previous Quiz Next final 限定符 在 C++11 中引入,主要有两个用途 −
📋 目录
  1. 将 final 限定符与 Class 一起使用
  2. 使用 final 说明符与 Function
  3. When to Use final Specifier?
  4. 结论
A A

C++ 中的 final 限定符



Previous
Quiz
Next

final 限定符 在 C++11 中引入,主要有两个用途 −

  • 第一个用途是防止继承。当一个 class 被标记为 final 时,其他 class 不能继承它。
  • 第二个用途是避免函数重写。当你将一个 virtual function 标记为 final 时,它就不能在派生类中被重写。

阅读本章以学习如何在 C++ 中使用 final 限定符。

将 final 限定符与 Class 一起使用

你可以将一个 class 标记为 final 来防止继承。标记为 final 后,你就不能再使用这个 class 进行继承。其他 class 将无法继承它。

将 final 限定符与 class 一起使用的语法如下 −

class MyClass final {
   // class members
};

示例

以下示例演示了使用 final 和不使用 final 的 class 之间的区别 −

Class with final Class without final

在这个示例中,我们在 Base class 上使用 final 限定符,而 Derived class 继承了基类。这将在输出中产生错误,如下所示 −

#include <iostream>
using namespace std;

class Base final // final class
{
   public:
   void display(){
      cout << "Base class" << endl;
   }
};

// Inheriting from final class
class Derived : public Base {
   public:
   void show(){
      cout << "Derived class" << endl;
   }
};

int main() {
   Base b;
   b.display();
   return 0;
}

上述代码的输出如下 −

main.cpp:14:7: error: cannot derive from 'final' base 'Base' in derived 
type 'Derived'
   14 | class Derived : public Base
      |       ^~~~~~~

在这个示例中,我们从 Base class 中移除了 final 限定符,Derived class 继承了基类。它不会产生任何错误,并将正常工作 −

#include <iostream>
using namespace std;

class Base  // removed final 
{
   public:
   void display(){
      cout << "Base class called" << endl;
   }
};

// Inheriting from non-final class
class Derived : public Base {
   public:
   void show(){
      cout << "Derived class called" << endl;
   }
};

int main(){
   Base b;
   b.display();
   return 0;
}

上述代码的输出如下 −

Base class called

使用 final 说明符与 Function

您可以使用 final 标记一个 function,以避免被覆盖该 function。标记一个 function 为 final 后,就无法再覆盖该 function。只有当 function 是virtual function时,才能将其标记为 final。

使用 final 说明符与 function 的语法如下所示 −

class Base {
   public:
   virtual void display() final {
      // 实现
   }
};

示例

下面的示例演示了使用 final 与不使用 final 时 function 的区别 −

Function with final Function without final

在这个示例中,我们在 Mammal class 的 virtual function breathe() 上使用了 final 说明符。在 Dog class 中,我们尝试覆盖 breathe() function,这将在输出中产生错误。

#include <iostream>
using namespace std;

class Animal {
   public:
   virtual void makeSound(){
      cout << "Animal sound" << endl;
   }

   virtual void breathe(){
      cout << "Animal breathing" << endl;
   }
};

class Mammal : public Animal {
   public:
   void makeSound() override{
      cout << "Mammal sound" << endl;
   }

   // final function
   void breathe() final override {
      cout << "Mammal breathing" << endl;
   }
};

class Dog : public Mammal{
   public:
   void makeSound() override {
      cout << "Bark" << endl;
   }

   // 这将导致错误
   void breathe() override { 
      cout << "Dog breathing" << endl;
   }
};

int main(){
   Dog dog;
   dog.makeSound(); 
   dog.breathe();   
   return 0;
}

上述代码的输出如下所示 −

main.cpp:42:10: error: virtual function 'virtual void Dog::breathe()' overriding 
final function
   42 |     void breathe() override
      |          ^~~~~~~
main.cpp:27:10: note: overridden function is 'virtual void Mammal::breathe()'
   27 |     void breathe() final override
      |          ^~~~~~~

在这个示例中,我们从 Mammal class 的 breathe() function 中移除了 final 说明符。在 Dog class 中覆盖 breathe() function 后,它将正常工作,不会产生任何错误,并在输出中打印覆盖后的值。

#include <iostream>
using namespace std;

class Animal {
   public:
   virtual void makeSound(){
      cout << "Animal sound" << endl;
   }

   virtual void breathe(){
      cout << "Animal breathing" << endl;
   }
};

class Mammal : public Animal{
   public:
   void makeSound() override {
      cout << "Mammal sound" << endl;
   }

   // 移除了 final 
   void breathe() override {
      cout << "Mammal breathing" << endl;
   }
};

class Dog : public Mammal{
   public:
   void makeSound() override {
       cout << "Bark" << endl;
   }

   // 现在这是安全的
   void breathe() override { 
      cout << "Dog breathing" << endl;
   }
};

int main(){
   Dog dog;
   dog.makeSound(); 
   dog.breathe();   
   return 0;
}

上述代码的输出如下所示 −

Bark
Dog breathing

结论

C++ 中的final 说明符有助于防止 class 的继承和 virtual function 的覆盖。在本章中,我们详细解释了 final 说明符如何与 class 和 virtual function 一起工作。