C++ 的 virtual 、abstract

时间: 2023-12-21 admin 维修知识

C++ 的 virtual 、abstract

C++ 的 virtual 、abstract

当在 C++ 中使用 virtual 和抽象类时,可以实现多态性和定义纯虚函数。下面我会详细解释这两个概念,并给出一个更详细的示例说明。

  1. virtual 关键字:

    • virtual 是用于实现多态性的关键字,它可以在基类中声明虚函数,并在派生类中进行重写。
    • 基类中的虚函数允许在运行时根据对象的实际类型来调用适当的函数,而不仅仅是根据指针或引用的静态类型。
    • 使用 virtual 关键字可以实现动态绑定(dynamic binding),也称为后期绑定(late binding)。
    • 通过在派生类中使用 override 关键字显式标记重写的函数,可以提高代码的可读性和可维护性。
  2. 抽象类和纯虚函数:

    • 抽象类是包含纯虚函数的类,无法实例化。它用于定义接口和行为的框架,而不需要实现具体的功能。
    • 纯虚函数是在基类中声明为虚函数并设置为纯虚的函数,通过在函数声明的末尾使用 = 0 来标识。
    • 派生类必须实现(重写)纯虚函数,否则它们也将成为抽象类。
    • 抽象类提供了一个统一的接口,派生类可以根据自身的特性来实现具体的行为。
    • 抽象类和纯虚函数提供了一种强制派生类实现特定功能的机制,促进了代码的灵活性和可扩展性。

下面是一个更详细的示例,说明 virtual 和抽象类的使用:

#include <iostream>class Shape {
public:virtual void draw() = 0;  // 纯虚函数,使 Shape 成为抽象类virtual double area() const = 0;  // 另一个纯虚函数virtual ~Shape() {}  // 虚析构函数,确保正确释放派生类资源
};class Circle : public Shape {
private:double radius;public:Circle(double r) : radius(r) {}void draw() override {std::cout << "Drawing a circle." << std::endl;}double area() const override {return 3.14159 * radius * radius;}~Circle() {std::cout << "Circle destructor called." << std::endl;}
};class Rectangle : public Shape {
private:double length;double width;public:Rectangle(double l, double w) : length(l), width(w) {}void draw() override {std::cout << "Drawing a rectangle." << std::endl;}double area() const override {return length * width;}~Rectangle() {std::cout << "Rectangle destructor called." << std::endl;}
};int main() {Shape* shapes[2];shapes[0] = new Circle(5.0);shapes[1] = new Rectangle(3.0, 4.0);for (int i = 0; i < 2; i++) {shapes[i]->draw();std::cout << "Area: " << shapes[i]->area() << std::endl;}delete shapes[0];delete shapes[1];return 0;
}

在上述示例中,Shape 是一个抽象类,它包含两个纯虚函数 draw()area()CircleRectangle 是派生类,它们继承自 Shape 并重写了这两个纯虚函数。

main() 函数中,我们创建了一个 Shape* 数组,并用 CircleRectangle 的对象初始化数组元素。通过使用基类指针调用 draw()area() 函数时,根据指针实际指向的对象类型,调用的是相应派生类的函数。这展示了多态性的作用,即在运行时根据对象的实际类型来动态绑定函数调用。

输出结果为:

Drawing a circle.
Area: 78.5398
Drawing a rectangle.
Area: 12
Circle destructor called.
Rectangle destructor called.

从输出结果可以看出,在循环中通过基类指针调用派生类的函数时,正确地调用了相应的派生类的函数。同时,在程序结束时,通过基类指针删除了派生类的对象,确保了正确的资源释放。

这个示例展示了 virtual 关键字的使用,它允许在派生类中重写基类的函数,并通过基类指针调用适当的派生类函数,实现了多态性。同时,抽象类和纯虚函数的使用定义了一个接口和行为的框架,要求派生类实现特定的功能,提高了代码的灵活性和可扩展性。