C++ 定义多态类

示例

典型的示例是抽象形状类,然后可以将其导出为正方形,圆形和其他具体形状。

父类:

让我们从多态类开始:

class Shape {
public:
    virtual ~Shape() = default;
    virtual double get_surface() const = 0;
    virtual void describe_object() const { std::cout << "this is a shape" << std::endl; }  

    double get_doubled_surface() const { return 2 * get_surface(); } 
};

如何阅读这个定义?

  • 您可以使用关键字引入成员函数来定义多态行为virtual。在这里get_surface(),describe_object()显然对于正方形和圆形的实现方式会有所不同。当在对象上调用该函数时,将在运行时确定与该对象的真实类相对应的函数。

  • 定义get_surface()抽象形状没有任何意义。这就是函数后面紧跟的原因= 0。这意味着该函数是纯虚函数

  • 多态类应始终定义虚拟析构函数。

  • 您可以定义非虚拟成员函数。当为对象调用这些函数时,将根据编译时使用的类来选择函数。这里get_double_surface()是用这种方式定义的。

  • 包含至少一个纯虚函数的类是抽象类。抽象类无法实例化。您可能只有抽象类类型的指针或引用。

派生类

一旦定义了多态基类,就可以派生它。例如:

class Square : public Shape {
    Point top_left;
    double side_length;
public: 
    Square (const Point& top_left, double side)
       : top_left(top_left), side_length(side_length) {}

    double get_surface() override { return side_length * side_length; }   
    void describe_object() override { 
        std::cout << "t他是一个正方形的开始 " << top_left.x << ", " << top_left.y
                  << " 长度为 " << side_length << std::endl; 
    }  
};

一些解释:

  • 您可以定义或覆盖父类的任何虚函数。函数在父类中是虚拟的事实使其在派生类中是虚拟的。无需virtual再次告诉编译器关键字。但是建议您override在函数声明的末尾添加关键字,以防止由于函数签名中未引起注意的变化而引起的细微错误。

  • 如果定义了父类的所有纯虚函数,则可以实例化该类的对象,否则它也将成为抽象类。

  • 您没有义务覆盖所有虚拟功能。如果需要,您可以保留父版本。

实例化的例子

int main() {

    Square square(Point(10.0, 0.0), 6); // 我们知道这是一个正方形,编译器也
    square.describe_object(); 
    std::cout << "Surface: " << square.get_surface() << std::endl; 

    Circle circle(Point(0.0, 0.0), 5);

    Shape *ps = nullptr;  // 我们还不知道对象的真实类型
    ps = &circle;         // 这是一个圆,但也可以是一个正方形
    ps->describe_object(); 
    std::cout << "Surface: " << ps->get_surface() << std::endl;
}