多态形成的三要素

2023-10-20 16:42:00 浏览数 (1)

上一篇文章中,我们看到了简单的赋值兼容模型,将子类赋值给父类对象时,调用共有的同名接口时,调用的依然还是父类的成员函数。在 C 中,有一个总要的概念,那就是多态。通过父类提供一些虚函数,让子类继承下去并实现为另外的功能,然后将子类对象的地址赋值给父类的对象指针。这样再次使用父类的指针调用共有同名接口时,你会发现它竟然调用的是子类的方法。这一切都来源于一个关键字“virtual”。

代码语言:javascript复制
#include 
using namespace std;
class Shape
{
public:
Shape(int x, int y)
:_x(x), _y(y){}
// 父类提供虚函数接口
virtual void draw()
{
cout << “draw Shap “;
cout << “start (“ << _x << “,” << _y << “)” << endl;
}
protected:
int _x;
int _y;
};
// 继承 Shape 类
class Circle : public Shape
{
public:
Circle(int x, int y, int r)
:Shape(x, y), _r(r){}
// 覆写父类 virtual 接口函数
void draw()
{
cout << “draw Circle “;
cout << “start (“ << _x << “,” << _y << “) “;
cout << “radio r = “ << _r << endl;
}
private:
int _r;
};
int main(int argc, char* argv[])
{
// 实例化一个父类对象
Shape s(3, 5);
s.draw();
// 实例化一个子类对象
Circle c(1, 2, 4);
c.draw();
cout << “————————“ << endl;
// 子类对象给父类变量赋值,普通赋值兼容,会出现数据截断
s = c;
s.draw();
// 子类对象给父类引用赋值,可构成多态
// 引用的内部实现就是包装了一个指针
Shape &rs = c;
rs.draw();
// 子类对象给父类指针赋值,可构成多态
Shape *ps = &c;
ps->draw();
return 0;
}

以上代码运行的结果你会发现,最后两个调用的draw都是子类的方法。

以上这种情况,被称为多态,当然你可能现在感觉不到它存在的意义,在以后的小案例中,你会不断的看到这种情况的出现。没有多态,C 可能没有那么出色。正是类和多态,给 C 带来了无数神秘的色彩。最后我们总结一下,多态形成的三个条件:

  1. 是父类中有虚函数。
  2. 子类 override(覆写)父类中的虚函数。
  3. 通过己被子类对象赋值的父类指针,调用共用接口。

0 人点赞