C++多态性总结

Wesley13
• 阅读 808

一,C++多态性概述

多态是指同样的消息被不同类型的对象接受时导致不同的行为。所谓消息是指对类的成员函数的调用,不同的行为是指不同的实现,也就调用不同的函数。换言之,多态指的就是用同样的接口访问功能不同的函数,从而实现“一个接口,多种方法”。

二,多态性分类

C++多态性总结

面向对象的多态性可以分为4类:重载多态,强制多态,包含多态,参数多态。前面两种统称专用多态,后面两种统称通用多态。

三,各种多态举例说明

1,重载多态:

重载多态包括前面学过的普通函数及类的成员函数的重载还有运算符的重载。 普通函数重载举例:

int add(int x, int y) {
    return x + y;
}
double add(double x, double y) {
    return x + y;
}
float add(float x, float y) {
    return x + y;
}

类的成员函数相当于函数在类的内部实现重载,在这儿就不详细说明了,跟普通函数重载大同小异。 下面重点介绍运算符号重载: 运算符重载是对已有的运算符赋予多重含义,使同一个运算符作用于不同类型的数据导致不同的行为。 运算符重载可以分为重载为成员函数以及重载为非成员函数两种。

重载为成员函数:

其一般语法形式为: 返回类型 operator 运算符(形参表) { 函数体 } 例1:(单目运算符)实现复数类前置++,后置++运算符重载

#include<iostream>
using namespace std;
class Complex {
public:
    Complex(double r = 0, double i = 0) :real(r), image(i) {}
    
    Complex& operator ++() {
        ++this->image;
        ++this->real;
        return (*this);

    };//前++

    Complex operator ++(int) {
        Complex temp = *this;
        ++(*this);//调用前置++
        return temp;
    };//后++
    
    void diaplayComplex() const {
        cout << "(" << this->real << "," << this->image << ")" << endl;
    };
private:
    double real;
    double image;

};


int main()
{
    Complex c1(1, 2);
    Complex c3(1, 2);
    Complex c2;
    c2=c1++;
    c1.diaplayComplex();
    c2.diaplayComplex();

    c2=++c3;
    c3.diaplayComplex();
    c2.diaplayComplex();
    return 0;
}

运行结果: C++多态性总结 这里需要注意的是前置++,返回值时Complex& 表示返回一个可修改的左值,后置++返回的是一个右值Complex ,另外,前置++形参表(),后置++形参表(int),只是对两种运算作区分。 例2:(双目运算符)重载运算符实现对复数的加法

#include"operator.h"
#include <iostream>
using namespace std;
class Complex {
public:
    Complex(double r = 0, double i = 0) :real(r), image(i) {}
    Complex operator +(const Complex &c) const;
    void diaplayComplex() const;
private:
    double real;
    double image;

};
Complex Complex::operator +(const Complex &c)const {
    return Complex::Complex(c.real + this->real, c.image + this->image);
};
void Complex::diaplayComplex() const {
    cout << "(" << this->real << "," << this->image << ")" << endl;
};
int main()
{
    Complex c1(1,2);
    Complex c2(1, 2);
    Complex c3;//保存运算结果
    Complex c4;//保存运算结果
    c3 = c1.operator+(c2);//传统方法调用
    c3.diaplayComplex();
    c4 = c1 + c2;//易懂的方法调用
    c4.diaplayComplex();
    return 0;
}

运行结果: C++多态性总结

重载为非成员函数:

一般语法形式:

返回类型 operator 运算符(形参表) { 函数体 } 例1:对类Point重载“++”(自增),"--"(自减)运算符,要求同时重载前缀和后缀的形式,重载为非成员函数。

//对类Point重载“++”(自增),"--"(自减)运算符,要求同时重载前缀和后缀的形式
#include "pch.h"
#include <iostream>
using namespace std;

class Point {
public:
    Point(int x=0, int y=0) :x(x), y(y) {}
    void showPoint();
    //以非成员函数类型实现
    friend Point& operator ++( Point&  p);
    friend Point operator ++(Point& p, int);

private:
    int x, y;
};
void Point::showPoint() {
    cout << "(" << x << "," <<y<< ")" << endl;
}
Point& operator ++( Point &p) {//前置++
    ++(p.x);
    ++(p.y);
    return p;
};
Point operator ++(Point& p, int) {//后置++
    Point t = p;
    ++p;
    return t;
};

int main()
{
    Point p1, p2, p3;
    p3 = p1++;
    p3.showPoint();
    p1.showPoint();
    cout << "------------------------------------------" << endl;
    p3 = ++p2;
    p3.showPoint();
    p2.showPoint();
    return 0;
}

运行结果: C++多态性总结 注意,重载为非成员函数时,需要声明为友元函数,这样才能访问类的私有数据成员,从而实现相应功能。

2,强制多态

是指讲一个变元的类型加以变化,以符合一个函数或者操作的要求,举一个简单例子就清楚啦。

int a=1;
float b=2.4f;
float re=a+b;

这里的加法运算符在进行浮点数和整形数相加时,首先进行类型强制转换,把整形数变为浮点数再相加的情况就是强制多态的实例。

3,包含多态

指的是类族中定义于不同类中的同名函数的多态的行为,主要是通过虚函数来实现。 那么什么是虚函数呢?

虚函数:

在类的成员函数前加virtual关键字。虚函数是实现包含多态的基础。这里需要说明的是当基类里有虚函数且派生类中重新声明了和基类虚函数相同的函数,那么派生类该函数也是虚函数,这个过程称为对基类虚函数进行重写,这对于实现包含多态有重要意义。

包含多态的条件:

基类中必须包含虚函数,并且派生类中一定要对基类中的虚函数进行重写。 通过基类对象的指针或者引用调用虚函数。 下面举个例子进行分析,看此段代码,实现了包含多态

//编写一个哺乳动物类Mammal,再由此派生出狗类Dog,Cat类,三者都声明speak()成员函数,该函数在基类中被声明为虚函数。

#include <iostream>
#include<string >
using namespace std;
class Mammal {
public:
    virtual void speak();
private:
    string name;
};
class Dog :public Mammal{
public:
     virtual void speak();
private:
    int age;

}; 
class Cat :public Mammal {
public:
    virtual void speak();
private:
    int age;

};
void fun(Mammal *m) {//通过传入不同对象的实参,可调用产生对应的成员函数,以实现多态的功能
    m->speak();
}
void Mammal::speak() { cout << "I don't know what to speak" << endl; };
void Dog::speak() { cout << "wang ~~~wang~~~ wang~~~" << endl; };
void Cat::speak() { cout << "miao ~~~miao~~~ miao~~~" << endl; };
int main()
{
    Dog d;
    Cat c;
    //传入不同对象的参数,实现相对应的功能(多态)
    fun(&d);
    fun(&c);

    return 0;
}

运行结果: C++多态性总结 这里speak()函数定义为virtual,然后通过

void fun(Mammal *m) {//通过传入不同对象的实参,可调用产生对应的成员函数,以实现多态的功能
    m->speak();
}

实现多态,注意fun()形式参数只能是基类对象指针或者引用。fun()函数也可以这样写,用基类引用实现:

void fun(Mammal &m) {//通过传入不同对象的实参,可调用产生对应的成员函数,以实现多态的功能
    m.speak();
}

纯虚函数与抽象类:

纯虚函数是一个在基类中声明的虚函数,它在该基类中没有定义具体的操作内容,要求各派生类根据实际需要给出各自的定义。纯虚函数的声明格式为: virtual 函数类型 函数名 (参数表)=0; 而抽象类就是指带有纯虚函数的类。 对上面的例子进行修改,用抽象类实现:

//编写一个哺乳动物类Mammal,再由此派生出狗类Dog,Cat类,三者都声明speak()成员函数,该函数在基类中被声明为虚函数。

#include <iostream>
#include<string >
using namespace std;
class Mammal {
public:
    virtual void speak()=0;
private:
    string name;
};
class Dog :public Mammal{
public:
     virtual void speak();
private:
    int age;

}; 
class Cat :public Mammal {
public:
    virtual void speak();
private:
    int age;

};
void fun(Mammal &m) {//通过传入不同对象的实参,可调用产生对应的成员函数,以实现多态的功能
    m.speak();
}
void Dog::speak() { cout << "wang ~~~wang~~~ wang~~~" << endl; };
void Cat::speak() { cout << "miao ~~~miao~~~ miao~~~" << endl; };
int main()
{
    Dog d;
    Cat c;
    //传入不同对象的参数,实现相对应的功能(多态)
    fun(d);
    fun(c);

    return 0;
}

这里需要注意的是抽象类不能进行实例化,如: C++多态性总结 就会报错: C++多态性总结

4,参数多态

采用函数模板,它可以用来创建一个通用的函数,以支持多种不同形参,避免重载函数的函数体重复设计,通过给出不同的类型参数,使得一个结构有多种类型。以实现参数多态。 定义的一般形式: template <模板参数表> 函数返回值类型 函数名(参数表) { 函数体
} 举例说明:下面是求绝对值得函数模板及其应用。

#include "pch.h"
#include <iostream>
using namespace std;
template <typename T>
T abs(T x)
{
    return x < 0 ? -x : x;
}

int main() {
    int a = 1;
    double b = -1;
    cout << abs(a) << endl;
    cout << abs(b) << endl;
    return 0;
}

运行结果: C++多态性总结

四,总结

多态性可以分为4类:重载多态,强制多态,包含多态,参数多态。 对于C++的多态性,这是一项很灵活的技术,用法十分灵巧。 简单来说:多态性就是适当的使用接口函数,通过一个接口来使用多种方法,(相当于上级说一个命令,甲乙丙丁等人都做出反应,一个命令,产生多个反应。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
小万哥 小万哥
1年前
C++虚函数详解:多态性实现原理及其在面向对象编程中的应用
在面向对象的编程中,多态性是一个非常重要的概念。多态性意味着在不同的上下文中使用同一对象时,可以产生不同的行为。C是一种面向对象的编程语言,在C中,虚函数是实现多态性的关键什么是虚函数虚函数是一个在基类中声明的函数,它可以被子类重写并提供不同的实现
Wesley13 Wesley13
3年前
C++课程第五次博客——多态
\TOC\多态性Part1多态性概述多态是指同样的消息被不同类型的对象接收时导致不同的行为。在C中,所谓信息是指对类的成员函数的调用,不同的行为是指不同的实现,也就是调用了不同的函数。1)多态的类型分为四类:重载多态,强制多态,包含多态和参数多态。前两者为专用多态,而后者称为通用多态。2)
Easter79 Easter79
3年前
Typescript 常见的几种函数重载方法详解与应用示例
所谓的重载,其实就是使用相同的函数名,传入不同数量的参数或不同类型的参数,以此创建出多个方法或产生不同结果。1\.最常见的,也就是根据定义傻瓜式地判断参数类型与数量functionshowPerson(name,...others){console.log(name,others)}
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
C++多态性与虚函数
  派生一个类的原因并非总是为了继承或是添加新的成员,有时是为了重新定义基类的成员,使得基类成员“获得新生”。面向对象的程序设计真正的力量不仅仅是继承,而且还在于允许派生类对象像基类对象一样处理,其核心机制就是多态和动态联编。(一)多态性  多态是指同样的消息被不同的对象接收时导致不同的行为。所谓消息是指对类成员函数的调用,不同的行为是指的不同的实现
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这