10 多态

多态

多态性:不同对象受到相同的消息时,产生不同的动作

  • 两种描述:

    • 具有不同功能的函数可以用同一个函数名

    • 指向不同的对象发送同一个消息,不同的对象在接收时会产生不同的行为

  • 多态的实现

    • 函数重载

    • 运算符重载

    • 虚函数

  • C++中的多态性可以分为四类

    • 通用多态

      • 参数多态:与类属函数和类属类相关联(函数模板和类模板就是这种多态)
      • 包含多态:研究类族中定义于不同类中的同名成员函数的多态行为(主要是通过虚函数来实现的)
    • 专用多态

      • 重载多态:普通函数及类的成员函数的重载多属于重载多态(如,函数重载、运算符重载等)
      • 强制多态:指一个变元的类型加以变化,以符合一个函数或操作的要求(例如加法运算符在进行浮点数与整形数相加时,首先进行强制转换,把整形数变为浮点数再相加的情况)
  • 从实现角度分:

    • 静态多态性——函数重载、运算符重载

    • 动态多态性——继承、虚函数

    • C++中,多态的实现和联编有关

      • 联编是把函数名和函数体的程序代码连接(联系)在一起的过程
      • 编译时的多态:静态联编,在编译阶段完成
        • 静态联编时,系统用实参和形成进行匹配,对于同名的重载函数便根据参数上的差异进行区分,然后进行联编。从而实现多态性。
      • 运行时的多态:动态联编,在运行阶段完成
        • 当程序调用到某一函数时,才去寻找和连接其程序代码,对面向对象的程序设计而言,就是当对象接收到某一消息时,采取寻找和连接对应的方法
    • 一般而言,编译型语言都采用静态联编,而解释性语言都采用动态联编

      • 纯粹的面向对象程序设计语言由于其执行机制是消息传递,所以只能采用动态联编。

      而为了保持C语言的高效性,C++仍是编译型的,仍采用静态联编;C++设计了“虚函数”的机制,解决了这个问题。

      C++实际上是采用了静态联编和动态联编相结合的联编方法。

      • 在C++中,编译时多态性主要是通过函数重载和运算符重载实现的。
      • 运行时多态性主要是通过虚函数来实现的。

Example 0. virtual function

#include <iostream>
using namespace std;
class Shape
{
protected:
    int width, height;

public:
    Shape(int a = 0, int b = 0) { width = a, height = b; }
    int area()
    {
        cout << "Parent class area: " << endl;
        return 0;
    }
};
class Rectangle : public Shape
{
public:
    Rectangle(int a = 0, int b = 0) : Shape(a, b) {}
    int area()
    {
        cout << "Rectangle class area: " << endl;
        return width * height;
    }
};
class Triangle : public Shape
{
public:
    Triangle(int a = 0, int b = 0) : Shape(a, b) {}
    int area()
    {
        cout << "Triangle class area: " << endl;
        return (width * height / 2); //这里int型,有点问题
    }
};
int main()
{
    Shape *shape;
    Rectangle rect(10, 7);
    Triangle tri(10, 5);
    shape = &rect;
    shape->area();
    shape = &tri;
    shape->area();
    return 0;
}
/*
Parent class area: 
Parent class area: 
*/
#include <iostream>
using namespace std;
class Shape
{
protected:
    int width, height;

public:
    Shape(int a = 0, int b = 0) { width = a, height = b; }
    virtual int area()	//虚函数
    {
        cout << "Parent class area: " << endl;
        return 0;
    }
};
class Rectangle : public Shape
{
public:
    Rectangle(int a = 0, int b = 0) : Shape(a, b) {}
    int area()
    {
        cout << "Rectangle class area: " << endl;
        return width * height;
    }
};
class Triangle : public Shape
{
public:
    Triangle(int a = 0, int b = 0) : Shape(a, b) {}
    int area()
    {
        cout << "Triangle class area: " << endl;
        return (width * height / 2); //这里int型,有点问题
    }
};
int main()
{
    Shape *shape;
    Rectangle rect(10, 7);
    Triangle tri(10, 5);
    shape = &rect;
    shape->area();
    shape = &tri;
    shape->area();
    return 0;
}
/*
Rectangle class area: 
Triangle class area: 
*/

Example 1. Point class,静态多态性,运算符重载

#include <iostream>
using namespace std;
class Point
{
protected:
    float x, y;

public:
    Point(float x = 0, float y = 0) : x(x), y(y) {} //有默认参数的构造函数
    void setPoint(float a, float b) { x = a, y = b; }
    float getX() const { return x; }
    float getY() const { return y; }
    friend 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(8.5, 6.8);
    cout << "p(new):" << p << endl;
    return 0;
}
/*
x=3.5,y=6.4
p(new):[8.5,6.8]
*/
#include <iostream>
using namespace std;
#define PI 3.14159
class Point
{
protected:
    float x, y;

public:
    Point(float x = 0, float y = 0) : x(x), y(y) {} //有默认参数的构造函数
    void setPoint(float a, float b) { x = a, y = b; }
    float getX() const { return x; }
    float getY() const { return y; }
    friend ostream &operator<<(ostream &output, const Point &p)
    {
        output << "[" << p.x << "," << p.y << "]" << endl;
        return output;
    }
};
class Circle : public Point
{
private:
    float radius;

public:
    Circle(float x = 0, float y = 0, float r = 0) : Point(x, y), radius(r) {}
    void setRadius(float r) { radius = r; }
    float getRadius() const { return radius; }
    float area() const { return PI * radius * radius; }
    friend ostream &operator<<(ostream &output, const Circle &c)
    {
        output << "Center=[" << c.x << "," << c.y << "], r="
               << c.radius << ", area=" << c.area() << endl;
        return output;
    }
};
int main()
{
    Circle c(3.5, 6.4, 5.2);
    cout << "original circle: x=" << c.getX()
         << ", y=" << c.getY()
         << ", r=" << c.getRadius()
         << ", area=" << c.area() << endl;
    c.setRadius(7.5);
    c.setPoint(5, 5);
    cout << "new circle: " << c;
    Point &pRef = c;
    cout << "pRef: " << pRef << endl;
    return 0;
}
/*
original circle: x=3.5, y=6.4, r=5.2, area=84.9486
new circle: Center=[5,5], r=7.5, area=176.714
pRef: [5,5]
*/
#include <iostream>
using namespace std;
#define PI 3.14159
class Point
{
protected:
    float x, y;

public:
    Point(float x = 0, float y = 0) : x(x), y(y) {} //有默认参数的构造函数
    void setPoint(float a, float b) { x = a, y = b; }
    float getX() const { return x; }
    float getY() const { return y; }
    friend ostream &operator<<(ostream &output, const Point &p)
    {
        output << "[" << p.x << "," << p.y << "]" << endl;
        return output;
    }
};
class Circle : public Point
{
private:
    float radius;

public:
    Circle(float x = 0, float y = 0, float r = 0) : Point(x, y), radius(r) {}
    void setRadius(float r) { radius = r; }
    float getRadius() const { return radius; }
    float area() const { return PI * radius * radius; }
    friend ostream &operator<<(ostream &output, const Circle &c)
    {
        output << "Center=[" << c.x << "," << c.y << "], r="
               << c.radius << ", area=" << c.area() << endl;
        return output;
    }
};
class Cylinder : public Circle
{
protected:
    float height;

public:
    Cylinder(float x = 0, float y = 0, float r = 0, float h = 0) : Circle(x, y, r), height(h) {}
    void setHeight(float h) { height = h; }
    float getHeight() const { return height; }
    float area() const { return 2 * Circle::area() + 2 * PI * Circle::getRadius() * height; }
    float volume() const { return Circle::area() * height; }
    friend ostream &operator<<(ostream &output, const Cylinder &cy)
    {
        output << "Center=[" << cy.x << "," << cy.y << "], r="
               << cy.getRadius() << ", h=" << cy.height
               << ", area=" << cy.area() << ", volume=" << cy.volume() << endl;
        return output;
    }
};
int main()
{
    Cylinder cy1(3.5, 6.4, 5.2, 10);
    cout << "original cylinder: x=" << cy1.getX()
         << ", y=" << cy1.getY()
         << ", r=" << cy1.getRadius()
         << ", h=" << cy1.getHeight()
         << ", area=" << cy1.area()
         << ", volume=" << cy1.volume() << endl;
    cy1.setHeight(15);
    cy1.setRadius(7.5);
    cy1.setPoint(5, 5);
    cout << "new cylinder: " << cy1;
    Point &pRef = cy1;
    cout << "pRef as a Point: " << pRef;
    Circle &cRef = cy1;
    cout << "cRef as a Circle: " << cRef;
    return 0;
}
/*
original cylinder: x=3.5, y=6.4, r=5.2, h=10, area=496.623, volume=849.486
new cylinder: Center=[5,5], r=7.5, h=15, area=1060.29, volume=2650.72
pRef as a Point: [5,5]
cRef as a Circle: Center=[5,5], r=7.5, area=176.714
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值