【多态性与虚函数的知识点】
创始人
2025-06-01 21:39:33

文章目录

  • 多态性与虚函数的知识点
    • 多态:
    • 虚函数:
      • 虚函数:
      • 虚函数的作用:
      • 虚函数的声明方法:
      • 虚函数的使用方法:
      • 虚函数使用注意:
      • 虚析构函数:
      • 纯虚函数与抽象类:
    • 多态与虚函数的实例:
  • 多态性与虚函数的实验结果
    • 多态与虚函数的实例1:
    • 多态与虚函数的实例2:

多态性与虚函数的知识点

多态:

  1. 多态:向不同的对象发送同一个消息,不同的对象在接收时会产生不同的行为(即方法)。(消息,就是指调用函数)

  2. 多态性分为两类:静态多态和动态多态。
    静态多态是通过函数的重载实现的,动态多态的特点是:不在编译时确定运行那个程序,而是在程序运行的过程中才确定操作所针对的对象。(运行时多态,是通过虚函数实现的)
    即如果通过对象名调用虚函数,属于静态关联。如果通过基类指针调用虚函数,为动态关联。

虚函数:

虚函数:

就是在基类声明函数是虚拟的,并不是实际存在的函数,然后在派生类中才正式定义的函数。

虚函数的作用:

允许在派生类中重新定义与基类同名的函数,并且可以通过基类指针或引用来访问基类和派生类中的同名函数。

虚函数的声明方法:

virtual 函数类型 函数名();

虚函数的使用方法:

(1)在类外定义虚函数时,不必再加virtual。
(2)在派生类中重新定义此函数,函数名,函数类型,函数参数个数和类型必须与基类的虚函数相同。
(3)当一个成员函数被声明为虚函数后,其派生类中的同名函数都自动成为虚函数。
(4)定义一个指向基类对象的指针变量,并使它指向同一类族中需要调用该函数的对象。
(5)通过指针变量调用此虚函数,此时调用的就是指针变量指向的对象的同名函数。
静态关联(函数重载)、早期关联/动态关联/滞后关联(程序运行阶段的多态性)

虚函数使用注意:

(1)只能使用virtual声明类的成员函数,而不能将类外的普通函数声明为虚函数。

(2)一个成员函数被声明为虚函数后,在同一类族中的类就不能再定义一个非virtual的但是与该虚函数具有相同的参数(包括个数和类型)和返回值类型的同名函数。

虚析构函数:

virtual ~classname( ) { … }
如果将基类的析构函数声明为虚函数,由该基类所派生的析构函数也都自动成为虚函数(即使派生类的析构函数与基类的析构函数名字不相同)。最好把基类的析构函数声明为虚函数。

纯虚函数与抽象类:

virtual 函数类型 函数名( 参数列表 ) =0;
纯虚函数没有函数体。 如果一个类中声明了纯虚函数,而在其派生类中没有对该函数定义,则该虚函数在派生类中仍然为纯虚函数。
抽象类:

1、唯一目的的就是用它去建立派生类,不能用来定义对象,只做为一种基本类型。
2、凡是包含纯虚函数的类都是抽象类,因为纯虚函数是不能被调用的,包含纯虚函数的类是无法建立对象的。
3、虽然抽象类不能定义对象,但是可以定义指向抽象类数据的指针变量

多态与虚函数的实例:

1.编写一个程序,声明抽象基类Shape,由它派生出3个派生类:Circle(圆形)、Rectangle(矩形)、Triangle(三角形),用一个函数pritArea分别输出以上三者的面积,3个图形的数据在定义对象时给定。

#include
using namespace std;
class Shape //定义抽象基类Shape
{
public:virtual double area() const = 0; //纯虚函数
};class Circle :public Shape //定义Circle类
{
public:Circle(double r) :radius(r) {} //结构函数virtual double area() const { return 3.14159 * radius * radius; }; //定义虚函数
protected:double radius; //半径
};class Rectangle :public Shape //定义Rectangle类
{
public:Rectangle(double w, double h) :width(w), height(h) {} //结构函数virtual double area() const { return width * height; } //定义虚函数
protected:double width, height; //宽与高
};class Triangle :public Shape //定义Triangle类
{
public:Triangle(double w, double h) :width(w), height(h) {} //结构函数virtual double area() const { return 0.5 * width * height; } //定义虚函数
protected:double width, height; //宽与高
};void printArea(const Shape& s) //输出面积的函数
{cout << s.area() << endl;
}int main()
{Circle circle(12.6); //建立Circle类对象circlecout << "area of circle=";printArea(circle); //输出circle的面积Rectangle rectangle(4.5, 8.4); //建立Rectangle类对象rectanglecout << "area of rectangle=";printArea(rectangle); //输出rectangle的面积Triangle triangle(4.5, 8.4); //建立Triangle类对象cout << "area of triangle=";printArea(triangle); //输出triangle的面积return 0;
}

2.编写一个程序,定义抽象基类Shape,由它派生出5个派生类:Cricle(圆形),Square(正方形), Rectangle(矩形), Trapezoid(梯形),Triangle(三角形)。用虚函数分别计算图形面积,并求所有图形面积的和。要求用基类指针数组,使它的每一个元素指向一个派生类对象。

#include
using namespace std;
class Shape //定义抽象基类Shape
{
public:virtual double area() const = 0; //纯虚函数
};class Circle :public Shape //定义Circle(圆形)类
{
public:Circle(double r) :radius(r) {} //构造函数virtual double area() const { return 3.14159 * radius * radius; }; //定义虚函数
protected:double radius; //半径
};class Square :public Shape //定义Square(正方形)类
{
public:Square(double s) :side(s) {} //构造函数virtual double area() const { return side * side; }  //定义虚函数
protected:double side;};class Rectangle :public Shape //定义Rectangle(矩形)类
{
public:Rectangle(double w, double h) :width(w), height(h) {} //结构函数virtual double area() const { return width * height; } //定义虚函数
protected:double width, height; //宽与高
};class Trapezoid :public Shape //定义Trapezoid(梯形)类
{
public:Trapezoid(double t, double b, double h) :top(t), bottom(t), height(h) {} //结构函数virtual double area() const { return 0.5 * (top + bottom) * height; } //定义虚函数
protected:double top, bottom, height; //上底、下底与高
};class Triangle :public Shape //定义Triangle(三角形)类
{
public:Triangle(double w, double h) :width(w), height(h) {} //结构函数virtual double area() const { return 0.5 * width * height; } //定义虚函数
protected:double width, height; //宽与高
};int main()
{Circle circle(12.6); //建立Circle类对象circleSquare square(3.5); //建立Square类对象squareRectangle rectangle(4.5, 8.4); //建立Rectangle类对象rectangleTrapezoid trapezoid(2.0, 4.5, 3.2); //建立Trapezoid类对象trapezoidTriangle triangle(4.5, 8.4); //建立Triangle类对象Shape* pt[5] = { &circle,&square,&rectangle,&trapezoid,&triangle }; //定义基类指针数组pt,使它每一个元素指向一个派生类对象double areas = 0.0; //areas为总面积for (int i = 0; i < 5; i++) areas = areas + pt[i]->area(); //累加面积cout << "total of all areas=" << areas << endl; //输出总面积return 0;
}

多态性与虚函数的实验结果

多态与虚函数的实例1:

在这里插入图片描述

多态与虚函数的实例2:

在这里插入图片描述


总结:通过这次实验了解到,如果在基类中定义了没有参数的构造函数,那么在定义派生类构造函数时可以不写基类构造函数,在调用派生类构造函数时、系统会自动首先调用基类的默认构造函数、如果在基类或子对象类型的声明中定义了参数的构造函数、那么就必须显式地定义派生类构造函数。动态联编需要满足3个条件,首先类之间满足类型兼容规则:第二是要声明虚函数:第三是要由成员函数来调用或者是通过基类指针、引用来访问虚函数。继承时,子类对基类的访问属性、基类的私有成员无论以何种方式继承在子类中都是不可访问的。唯有调用基类中的成员函数方可访问其私有变量。另外、派生类构造函数的总参数列表中的参数,应当包括基类构造函数和子对象的参数列表中的参数。而多层派生时、只需写出其直接基类的构造函数即可。虚函数可以让代码重用,用一个界面的不同表示方法,增加功能的分类,使相近的功能不同但是类似的表示,同时虚函数和多态的使用在程序更新时让类库更加方便。

相关内容

热门资讯

王传福:我直管的总经理,一半出...   炒股就看金麒麟分析师研报,权威,专业,及时,全面,助您挖掘潜力主题机会! (来源:第一财经资讯...
财联社创投通:一级市场本周融资... 转自:财联社【财联社创投通:一级市场本周融资总额约132.73亿元环比增加84.04% 先进制造、医...
市妇联: 架起维权公益服务“连... (来源:廊坊日报)转自:廊坊日报 本报讯(记者 陈正)自全市“法治为民·法治护企办实事”活动...
“中国茅台号”“茅台1935号... (来源:文旅中国)12月26日,由中国贵州茅台酒厂(集团)有限责任公司与多彩贵州航空公司联合打造的“...
连续四个月保持增长!重要数据公... 国家统计局12月27日发布数据显示,1—11月份,全国规模以上工业企业实现利润总额66268.6亿元...