C++学习-多态性与虚函数

多态性

概念:向不同的对象发送同一个消息,不同的对象在接收时会产生不同的行为(即方法)。
作用:可以实现一个接口,多种方法
应用:多态性分为静态多态性和动态多态性,静态多态性即编译时的多态性,通过函数重载实现;动态多态性是运行时才确定操作所作用的对象,动态多态性通过虚函数(virtual function)实现;


例子:
建立一个Point(点)类,包含数据成员x,y(坐标点)。以它为基类,派生出一个Circle(圆)类,增加数据成员r(半径),再以Circle类为直接基类,派生出一个Cylinder(圆柱体)类,再增加数据成员h(高)。要求编写程序,重载运算符“<<”和“>>”,使之能用于输出以上类对象。

对于一个比较大的程序,应当分成若干步骤进行。先声明基类,再声明派生类,逐级进行,分步调试。

//首先实现基类point
#include <iostream>
using namespace std;

class point
{
public:
    point(float x=0, float y=0);//构造函数,初始化坐标(0,0)
    void setPoint(float, float);
    float getx() const {return x;}
    float gety() const {return y;}
    friend ostream & operator<<(ostream &, const point &);

protected:
    float x, y;
};

void point::setPoint(float a, float b)
{
    x = a;
    y = b;
}
point::point(float a, float b)
{
    x = a;
    y = b;
}
ostream & operator<<(ostream & output, const point & p)
{
    output << "[" << p.x << "," << p.y << "]" << endl;
    return output;
}
int main()
{
    point p(3.5, 6.4); 
    cout<<"x="<<p.getx()<< "   y=" << p.gety()<<endl;
    p.setPoint(1.1,3.2);
    cout << "pnew = " << p << endl;
}
//输出结果
x=3.5   y=6.4
pnew = [1.1,3.2]
//声明派生类circle
//派生类

class circle:public point
{
public:
    circle(float x=0, float y=0, float r=0);//构造函数
    void setRadius(float);//设置半径值
    float getRadius() const;
    float area() const;//计算圆面积
    friend ostream  &operator<<(ostream &, const circle &);//重载运算符<<,输入参数为一个输出流引用及circle对象引用

private:
    float radius;

};
//定义构造函数,对圆心坐标和半径初始化
circle::circle(float a, float b, float r):point(a,b),radius(r)
{

}

void circle::setRadius(float r)
{
    radius = r;
}
float circle::getRadius() const
{
    return radius;
}

ostream & operator<<(ostream & output, const circle & c)
{
    output << "Center = [" << c.x << "," << c.y<< "], r = " << c.radius << ", area = " << c.area() << endl;
    return output;
}

float circle::area() const
{
    float radius = getRadius();
    return 3.14159*radius*radius;
}

将int main(){}更改为:

int main()
{
    point p(3.5, 6.4); //p
    cout<<"x="<<p.getx()<< "   y=" << p.gety()<<endl;
    p.setPoint(1.1,3.2);
    cout << "pnew = " << p << endl;
    circle c(2.5, 6.4, 4.3);//建立circle对象,并给出圆心和半径
    cout << "origina circle:" << c.getx() << ", y = " << c.gety() << ", r = " << c.getRadius() << ", area = " << c.area() << endl;
    c.setRadius(7.0);
    c.setPoint(2.0, 2.0);
    cout << "new circle:" << c;
    point &pRef = c;
    cout << "pRef:" << pRef;
    return 0;
}
//运行结果
x=3.5   y=6.4
pnew = [1.1,3.2]

origina circle:2.5, y = 6.4, r = 4.3, area = 58.088
new circle:Center = [2,2], r = 7, area = 153.938
pRef:[2,2]

接下来再从派生类circle派生出cylinder类

//cylinder类
//增加高度属性
//声明circle的派生类cylinder
class cylinder:public circle
{
public:
    cylinder(float x=0, float y=0, float r=0, float h=0);//构造函数
    void setHeight(float);//设置圆柱高
    float getHeight() const;//获取圆柱高度
    float volume() const;//计算圆柱体积
    friend ostream & operator<<(ostream &, const cylinder &);

private:
    float height;//圆柱高度
};

cylinder::cylinder(float a, float b, float r, float h)
    :circle(a, b, r),height(h)
{

}

void cylinder::setHeight(float h)
{
    height = h;
}

float cylinder::getHeight() const
{
    return height;
}

float cylinder::volume() const
{
    float height = getHeight();
    float area = circle::area();
    return (area*height);
}
//重载运算符 <<
ostream & operator<<(ostream & output, const cylinder & cy)
{
    output << "Center = [" << cy.x << cy.y << "]" << ", r = " << cy.getRadius() << ", h = " << cy.height
           << "\narea = " << cy.area() << ", volume = " << cy.volume() << endl;
    return output;
}

将int main(){}更改为:

int main()
{
    //point test
    point p(3.5, 6.4); //p
    cout<<"x="<<p.getx()<< "   y=" << p.gety()<<endl;
    p.setPoint(1.1,3.2);
    cout << "p-new = " << p << endl;

    //circle test
    circle c(2.5, 6.4, 4.3);//建立circle对象,并给出圆心和半径
    cout << "origina circle:x = " << c.getx() << ", y = " << c.gety() << ", r = " << c.getRadius() << ", area = " << c.area() << endl;
    c.setRadius(7.0);
    c.setPoint(2.0, 2.0);
    cout << "new circle:" << c;
    point &pRef = c;
    cout << "pRef:" << pRef;

    //cylinder test
    cylinder cy(3.2, 7.6, 7.5, 4.3);//建立cylinder对象,并给出圆心,半斤,高度
    cout << "original cylinder:x = " << cy.getx() << ", y = " << cy.gety() << ", r = " << cy.getRadius() << ", h = " << cy.getHeight() << endl;
    cy.setPoint(1.0, 1.0);
    cy.setRadius(3.0);
    cy.setHeight(6.5);
    cout << "new cylinder:" << cy;
    point &pRef1 = cy;
    cout << pRef1;//作为点输出
    circle &pRef2 = cy;
    cout << pRef2;//作为圆输出
    return 0;
}

输出:

x=3.5   y=6.4
p-new = [1.1,3.2]

origina circle:x = 2.5, y = 6.4, r = 4.3, area = 58.088
new circle:Center = [2,2], r = 7, area = 153.938
pRef:[2,2]
original cylinder:x = 3.2, y = 7.6, r = 7.5, h = 4.3
new cylinder:Center = [11], r = 3, h = 6.5
area = 28.2743, volume = 183.783
[1,1]
Center = [1,1], r = 3, area = 28.2743

上例的静态多态性是运算符重载引起的。可以看到,在编译时编译系统即可以判定应调用哪个重载运算符函数。稍后将在此基础上讨论动态多态性问题。


动态多态性通过虚函数实现:
虚函数的作用是允许在派生类中重新定义与基类同名的函数,并且可以通过基类指针或引用来访问基类和派生类中的同名函数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值