多态的作用

        多态是面向对象编程中的一种重要概念,它允许不同的对象以各自独特的方式对同一消息进行响应。多态性是继承和虚函数的必然结果,它使得程序更加灵活和可扩展,能够提高代码的可维护性和可重用性。

        可扩展性: 在面向对象编程中,多态可以提高代码的可扩展性。通过继承,子类可以扩展或重写父类的功能,而多态性使得程序能够以同一种方式处理不同的子类对象。这样,当需要增加新的子类时,只需要定义新的子类,而无需修改已有代码,从而提高了代码的可扩展性。

例一:

class Shape {
public:
  virtual void Draw() = 0;
};

class Circle : public Shape {
public:
  void Draw() override { cout << "Draw Circle" << endl; }
};

class Square : public Shape {
public:
  void Draw() override { cout << "Draw Square" << endl; }
};

void DrawAllShapes(vector<Shape*>& shapes) {
  for (auto s : shapes) {
    s->Draw();
  }
}

int main() {
  vector<Shape*> shapes;
  shapes.push_back(new Circle());
  shapes.push_back(new Square());
  DrawAllShapes(shapes);
  return 0;
}

        在例一中,Shape是一个抽象基类,它定义了Draw()纯虚函数。Circle和Square是Shape的具体子类,并分别实现了Draw()函数。在DrawAllShapes()函数中,通过遍历shapes数组并调用每个元素的Draw()函数,实现了不同形状的绘制,而不需要修改已有的代码。

        可维护性: 多态也可以提高代码的可维护性。当需要修改某个功能时,只需要修改相关的类的实现,而不需要修改调用该功能的代码。这样可以保证程序的其他部分不会受到影响。

        可重用性: 多态还可以提高代码的可重用性。多态允许我们将父类指针或引用指向子类对象,从而能够方便地复用代码。这样,我们可以使用同样的代码处理不同的对象,并且可以在不同的上下文中重用相同的代码。

例二:

class Animal {
public:
  virtual void Speak() = 0;
};

class Dog : public Animal {
public:
  void Speak() override { cout << "Bark!" << endl; }
};

class Cat : public Animal {
public:
  void Speak() override { cout << "Meow!" << endl; }
};

void MakeAnimalSpeak(Animal* animal) {
  animal->Speak();
}

int main() {
  Animal* dog = new Dog();
  Animal* cat = new Cat();
  MakeAnimalSpeak(dog);
  MakeAnimalSpeak(cat);
  return 0;
}

        在例二中,我们定义了一个抽象基类`Animal`,并派生出两个子类`Dog`和`Cat`。`Animal`类有一个纯虚函数`Speak`,该函数需要在派生类中被实现。`Dog`类和`Cat`类分别重写了`Speak`函数,并分别输出`"Bark!"`和`"Meow!"`。 

        主函数中,通过`new`关键字创建一个`Dog`对象和一个`Cat`对象,分别赋给基类指针`Animal* dog`和`Animal* cat`。然后,通过调用`MakeAnimalSpeak`函数,将这两个指针传递给该函数进行处理。在`MakeAnimalSpeak`函数内部,调用了传入对象的`Speak`函数,由于在运行时进行虚函数绑定,因此将会分别输出`"Bark!"`和`"Meow!"`。 

        这种通过基类指针或引用调用派生类对象的方式称为多态。多态性使得可以通过基类接口来操作派生类对象,从而简化了程序设计,提高了代码的可扩展性和可维护性。

       再举一个例子,假设我们有一个图形类 Shape,有多个派生类如矩形 Rectangle、圆形 Circle、三角形 Triangle 等,它们都有各自的计算面积和周长的方法。

        如果我们使用静态多态(函数重载),则每个图形都需要写自己的面积和周长计算函数,并在使用时手动选择合适的函数。代码可能会像这样:

class Shape {
public:
    virtual double area() = 0;
    virtual double perimeter() = 0;
};

class Rectangle : public Shape {
public:
    double area() override { /* 计算矩形面积 */ }
    double perimeter() override { /* 计算矩形周长 */ }
};

class Circle : public Shape {
public:
    double area() override { /* 计算圆形面积 */ }
    double perimeter() override { /* 计算圆形周长 */ }
};

class Triangle : public Shape {
public:
    double area() override { /* 计算三角形面积 */ }
    double perimeter() override { /* 计算三角形周长 */ }
};

// 在使用时需要手动选择合适的函数
void printShapeInfo(Shape* shape) {
    if (dynamic_cast<Rectangle*>(shape)) {
        std::cout << "矩形,面积:" << shape->area() << ",周长:" << shape->perimeter() << std::endl;
    } else if (dynamic_cast<Circle*>(shape)) {
        std::cout << "圆形,面积:" << shape->area() << ",周长:" << shape->perimeter() << std::endl;
    } else if (dynamic_cast<Triangle*>(shape)) {
        std::cout << "三角形,面积:" << shape->area() << ",周长:" << shape->perimeter() << std::endl;
    }
}

使用动态多态(虚函数重写)的话,我们只需要在基类中声明虚函数,然后在每个派生类中重写该函数,即可实现多态特性,使得代码更加灵活和可扩展,如下所示:

class Shape {
public:
    virtual double area() = 0;
    virtual double perimeter() = 0;
    virtual ~Shape() = default; // 声明虚析构函数,以确保正确销毁派生类对象
};

class Rectangle : public Shape {
public:
    double area() override { /* 计算矩形面积 */ }
    double perimeter() override { /* 计算矩形周长 */ }
};

class Circle : public Shape {
public:
    double area() override { /* 计算圆形面积 */ }
    double perimeter() override { /* 计算圆形周长 */ }
};

class Triangle : public Shape {
public:
    double area() override { /* 计算三角形面积 */ }
    double perimeter() override { /* 计算三角形周长 */ }
};

// 使用动态多态调用虚函数,无需手动选择合适的函数
void printShapeInfo(Shape* shape) {
    std::cout<< "Shape area: " << shape->area() << std::endl;
std::cout << "Shape perimeter: " << shape->perimeter() << std::endl;
}

int main() {
// 创建不同形状的对象,传递给printShapeInfo函数进行打印
Rectangle rect;
Circle circle;
Triangle tri;
printShapeInfo(&rect);
printShapeInfo(&circle);
printShapeInfo(&tri);

return 0;
}

        以上代码中,定义了一个基类Shape,并声明了两个纯虚函数area()perimeter(),派生类RectangleCircleTriangle分别重写了这两个函数,从而实现了自己特定形状的计算。在printShapeInfo()函数中,传入一个指向Shape对象的指针,通过虚函数机制实现动态多态,调用具体派生类实现的area()perimeter()函数,无需手动选择合适的函数。这种方式提高了代码的可扩展性和可维护性,可以轻松地添加新的派生类实现新的形状,同时也提高了代码的可重用性,可以在不同的上下文中使用Shape对象进行计算。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

漂流刑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值