📜  从基类和抽象类派生的类中虚函数的行为(1)

📅  最后修改于: 2023-12-03 15:36:17.074000             🧑  作者: Mango

从基类和抽象类派生的类中虚函数的行为

在 C++ 中,我们可以使用类的继承特性来进行代码重用和扩展功能。派生类可以从一个或多个基类继承属性和方法,其中包括虚函数。虚函数是在基类声明中带有关键字 virtual 的函数。在派生类中,我们可以对虚函数进行重写,从而改变虚函数的行为。

基类和派生类中的虚函数

在 C++ 中,虚函数是指在基类中声明为虚函数的函数,它在派生类中可以被重写,以改变其行为。在基类中,我们可以使用虚函数来定义一个接口,然后在派生类中实现该接口。这使得我们可以封装对象的具体实现细节,只留下一个抽象的接口。

class Shape {
   public:
      // 基类虚函数
      virtual double area() {
         cout << "Shape 的面积是:" << endl;
         return 0;
      }
};

class Rectangle: public Shape {
   public:
      // 派生类虚函数
      double area () { 
         cout << "Rectangle 的面积是:" << endl;
         return (width * height); 
      }
};

class Triangle: public Shape{
   public:
      // 派生类虚函数
      double area () { 
         cout << "Triangle 的面积是:" << endl;
         return (width * height / 2); 
      }
};

在上面的代码中,我们定义了一个基类 Shape,其中声明了虚函数 area()。然后我们派生了两个类 Rectangle 和 Triangle,并对 area() 进行了重写。

抽象类和纯虚函数

抽象类是指包含至少一个纯虚函数的基类。纯虚函数是一种在基类中声明但没有实现的虚函数,需要在派生类中进行实现,否则该派生类也将变成一个抽象类。

class Shape {
   public:
      // 纯虚函数
      virtual double area() = 0;
};

在上面的代码中,我们将虚函数 area() 声明为纯虚函数。这使得 Shape 成为一个抽象类,需要在派生类中实现其中的纯虚函数。

class Rectangle: public Shape {
   public:
      double area () { 
         cout << "Rectangle 的面积是:" << endl;
         return (width * height); 
      }
};

class Triangle: public Shape{
   public:
      double area () { 
         cout << "Triangle 的面积是:" << endl;
         return (width * height / 2); 
      }
};

在上面的代码中,我们将 Rectangle 和 Triangle 派生自 Shape,并实现其中的纯虚函数 area()。这使得这两个类不再是抽象类,并且可以被实例化。

虚函数表和虚函数指针

为了实现虚函数,每个对象都需要一个额外的元数据来存储虚函数表(vtable),该表用于存储虚函数的地址。每个具有虚函数的类都有其自己的虚函数表,并且派生类的虚函数表中也包含基类的虚函数表中的所有虚函数。

在对象的内存布局中,还会有一个指向虚函数表的指针,称为虚函数指针(vpointer),该指针指向这个类的虚函数表。当调用虚函数时,会根据这个指针来调用正确的虚函数。

总结

在 C++ 中,虚函数是基于在运行时动态绑定实现多态性的一种机制。通过在基类中声明虚函数,在派生类中进行重写,我们可以实现多态性和抽象化,并且可以有效地进行代码的重用和扩展。此外,抽象类和纯虚函数是一种实现抽象化的工具,允许我们定义接口而不指定其实现,这使得代码更容易扩展和维护。