c++多态

  • 所谓多态,就是不同类的对象的同一方法表现出不同的形态。比如定义一个铃响的方法,一些对象去食堂用餐,另一个对象下班回家
  • 实现多态的三个必要条件
类之间存在继承关系
不同类的同一方法以虚函数的方法实现(virtual重写)
基类指针指向子类对象
  • virtual多态关键字的意义,告诉编译器该函数要实现多态,不是根据指针类型判断如何调用,而是根据指针指向的对象类型来调用
  • 从现象看定义一个基类mycoach和子类studentcoach,他们都实现了一个·gethint()方法,这里我们假定搏击名将居马别克(基类实现)是搏击小将陈培昌(继承基类的子类)的老师
  • mycoach类实现
#pragma once
#include<iostream>
#include<string>
using namespace std;
class mycoach
{
private:
    string name;
    string addr;
    int age;
    string item;
    string place="热瓦甫新疆大餐厅";
public:
    mycoach::mycoach(string name,int age,string addr)
    {
        this->name = name;
        this->age = age;
        this->addr = addr;
        cout << ".........." << endl;
    }

    
    virtual void gethint(string item = "登山",string hint="内地朋友请注意呼吸,如果不舒服,就歇一会儿")
    {
        cout << "亲爱的朋友们!我是:" << this->name << ",欢迎参加----" << this->addr << endl;
        cout << "让我们来训练" << item << endl;
        cout << hint << endl;
        cout << "阿依古丽,带领姑娘们准备好担架,和骆驼队" << endl;
    }

    ~mycoach()
    {
        cout << "mycoach析构开始调用........." << endl;
        cout << "今天的训练先告一段落,下一个目标:" << this->place << ",let's go " <<endl;
    }
};
  • studentcoach类实现
#pragma once
#include "mycoach.h"
using namespace std;
class studentcoach:public mycoach
{
private:
    string name;
    int age;
    string item;
    string addr;
    string place = "省港茶餐厅";

public:
    studentcoach::studentcoach(string name,int age,string addr):mycoach(name, age, addr),name(name)
    {
        //this->name = name;
        this->age = age;
        this->addr = addr;

    }

    void gethint(string item = "登山", string hint = "北方的朋友要siao(小)心山蚂蟥")
    {
        cout << "大嘎(家)好!唔系:" << this->name << ",欢迎参加----" << this->addr << endl;
        cout << "让我们来训练" << item << endl;
        cout << hint << endl;
        cout << "阿珍,叫王刘发娟,林许家娇,大嘎(家)准备好医疗用品" << endl;
    }

    ~studentcoach()
    {
        cout << "studentcoach析构开始调用........." << endl;
        cout << "今天的训练先告一段落,阿发,骑猛犸大三轮,带大家去---" << this->place << ",丁大锅跟我一辆车 " << endl;
    }
};
  • 主函数中定义的方法
#include<iostream>
#include"mycoach.h"
#include"studentcoach.h"

using namespace std;


void startpractise(mycoach *coach,string item="登山",string hint="内地的朋友,请到呼斯满那集合,他将带领你们适应高原的训练")
{
    coach->gethint(item,hint);//这里将实现多态,而不仅仅是父类的方法
}

void showdemo()//这种刻意封装是为了函数执行完,回收内存空间时触发对象的析构函数,以便看到对象析构函数执行效果
{
    mycoach jmbk("居马别克", 34, "天山搏击训练营");
    //jmbk.gethint("长跑","内地的朋友,请到呼斯满那集合,他将带领你们适应高原的训练");
    startpractise(&jmbk);
    studentcoach cpc("陈培昌", 22, "粤港人搏击俱乐部");
    startpractise(&cpc, "登山", "北方的朋友要siao(小)心山蚂蟥");
    //cpc.gethint();
}

int main()
{
    showdemo();
    system("pause");
    return 0;
}

输出结果:

..........
亲爱的朋友们!我是:居马别克,欢迎参加----天山搏击训练营
让我们来训练登山
内地的朋友,请到呼斯满那集合,他将带领你们适应高原的训练
阿依古丽,带领姑娘们准备好担架,和骆驼队
..........
大嘎(家)好!唔系:陈培昌,欢迎参加----粤港人搏击俱乐部
让我们来训练登山
北方的朋友要siao(小)心山蚂蟥
阿珍,叫王刘发娟,林许家娇,大嘎(家)准备好医疗用品
studentcoach析构开始调用.........
今天的训练先告一段落,阿发,骑猛犸大三轮,带大家去---省港茶餐厅,丁大锅跟我一辆车
mycoach析构开始调用.........
今天的训练先告一段落,下一个目标:热瓦甫新疆大餐厅,let's go
mycoach析构开始调用.........
今天的训练先告一段落,下一个目标:热瓦甫新疆大餐厅,let's go
请按任意键继续. . .

  • 多态实现原理
如果类中声明了virtual函数,编译器会做两件事情,创建一个虚函数列表,存入指向虚函数的指针;为对象创建一个vptr指针
运行时,根据对象的vptr指针指向的虚函数表中查找到相关函数,并调用
查找和调用都在运行时进行----这就是所谓的动态联编
也不难看出,virtual函数的执行涉及了寻址操作,这与普通函数在编译时就确定调用相比,多了些操作,势必造成性能开销,所以没必要把每一个成员函数都声明为virtual类型
原文地址:https://www.cnblogs.com/saintdingspage/p/12030928.html