开发者社区> CtrlX> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

C++多态的基本概念与原理刨析

简介: 多态分为两类 • 静态多态: 函数重载 和 运算符重载属于静态多态,复用函数名 • 动态多态: 派生类和虚函数实现运行时多态 静态多态和动态多态区别: • 静态多态的函数地址早绑定 - 编译阶段确定函数地址 • 动态多态的函数地址晚绑定 - 运行阶段确定函数地址 下面通过案例进行讲解多态
+关注继续查看



多态的基本概念

多态是C++面向对象三大特性之一

多态分为两类

  • 静态多态: 函数重载 和 运算符重载属于静态多态,复用函数名
  • 动态多态: 派生类和虚函数实现运行时多态

静态多态和动态多态区别:

  • 静态多态的函数地址早绑定 - 编译阶段确定函数地址
  • 动态多态的函数地址晚绑定 - 运行阶段确定函数地址

下面通过案例进行讲解多态

class Animal

{

public:

    void speak()

    {

        cout << "动物在说话" << endl;

    }

};

class Cat :public Animal

{

public:

    void speak()

    {

        cout << "小猫在说话" << endl;

    }

};

void DoSpeak(Animal & animal)

{

    animal.speak();

}

void test01()

{

    Cat cat;

    DoSpeak(cat);//想让猫说话,但是输出结果是动物说话

}

int main() {

    test01();

    system("pause");

    return 0;

}

案例分析:

想让猫说话,但是输出结果是动物说话,原因是因为执行说话的函数speak()地址早绑定了,在编译阶段就已经确定了函数地址。

如果想执行猫说话,那么这个函数地址就不能提前绑定,需要在运行阶段绑定。

解决方案:

class Animal

{

public:

   //Speak函数就是虚函数

    //函数前面加上virtual关键字,变成虚函数,那么编译器在编译的时候就不能确定函数调用了。

    virtual void speak()

    {

        cout << "动物在说话" << endl;

    }

};

class Cat :public Animal

{

public:

    

    void speak()

    {

        cout << "小猫在说话" << endl;

    }

};

void DoSpeak(Animal & animal)

{

    animal.speak();

}

void test01()

{

    Cat cat;

    DoSpeak(cat);//使用了虚函数后,输出结果:小猫在说话

}

int main() {

    test01();

    system("pause");

    return 0;

}

相当于speak()现在有多种形态了,根据传入的对象不同确定不同的函数地址。

总结:

多态满足条件

  • 有继承关系
  • 子类重写父类中的虚函数,子类可写可不写

多态使用条件

  • 父类指针引用指向子类对象

PS:

  • 重写:函数返回值类型 函数名 参数列表 完全一致称为重写
多态的原理刨析

class Animal

{

public:

    //Speak函数就是虚函数

    //函数前面加上virtual关键字,变成虚函数,那么编译器在编译的时候就不能确定函数调用了。

    virtual void speak()

    {

        cout << "动物在说话" << endl;

    }

};

class Cat :public Animal

{

public:

    void speak()

    {

        cout << "小猫在说话" << endl;

    }

};

//我们希望传入什么对象,那么就调用什么对象的函数

//如果函数地址在编译阶段就能确定,那么静态联编

//如果函数地址在运行阶段才能确定,就是动态联编

void DoSpeak(Animal & animal)

{

    animal.speak();

}

//多态满足条件:

//1、有继承关系

//2、子类重写父类中的虚函数

//多态使用:

//父类指针或引用指向子类对象

void test01()

{

    Cat cat;

    DoSpeak(cat);

}

void test02()

{

   cout << sizeof(Animal) << endl;

}

int main() {

    test02();

    system("pause");

    return 0;

}

案例分析:

在Animal中的speak()函数为加上关键字virtual时是一个非静态成员函数,不属于类的对象上,该类类似于一个空类,占一个字节,

加上关键字后运行发现这个类占4个字节(PS:不管什么指针都占4个字节,可以考虑指针),多了一个vfptr(virtual function pointer虚函数(表)指针),指向vftable(虚函数表)

子类的替换继承过来的父类的speak()


版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
BPMN工作流的基本概念!详解工作流框架Activiti
本文介绍了工作流的基本概念,对工作流中的相关术语,例如工作流引擎,BPM,BPMN以及流对象进行说明。着重介绍了当下非常流行的工作流框架Activiti,重点介绍了工作流框架Activiti的服务结构,工作流组件,流程虚拟机PVM以及工作流框架的架构和使用特点。通过这篇文章,可以对工作流有一个基本的认识,为后续工作流框架Activiti的学习打下坚实的基础。
416 0
Win10系统下eclipse的基本配置 编码格式 classpath原理 import工作机制
eclipse是用来编译java文件的一个软件 国内也有汉化版,我也不知道该怎么上传……忘了从哪里搞来了 不过用了一段时间就还原原来的配置了因为网上的教程之类的方法都是英文版的 为了和网上的配套我也就用回了英文原版。
1812 0
Lucene: 全文检索的基本原理
转自:http://blog.csdn.net/forfuture1978/archive/2009/10/22/4711308.aspx 转自:https://www.
698 0
《云安全原理与实践》——1.2 云计算的基本概念
本节书摘来自华章计算机《云安全原理与实践》一书中的第1章,第1.2节,作者:陈兴蜀,葛龙著, 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
1744 0
Git的基本原理与常用命令[二]
标签(linux): git 笔者Q:972581034 交流群:605799367。有任何疑问可与笔者或加群交流 git 的四个区域 四种状态 常用命令 git add #加入暂存(索引区) git status #查看状态 git stat...
771 0
《HTML5+JavaScript动画基础》——第1章 动画的基本概念 1.1动画
动画是运动。运动是一个物体随着时间在空间中改变它的位置,前一分钟它在这里,下一分钟它到了那里。将数学公式应用于改变一个物体的位置后,你就可以决定它的下一个位置并影响运动的行为,也就赋予了物体生命
1528 0
重载的基本概念
当运算符被用于类类型的对象时,C++语言允许我们为其指定新的含义;同时,我们也能自定义类类型之间的转换规则。和内置类型的转换一样,类类型转换隐式地将一种类型的对象转换成另一种我们所需类型的对象。
471 0
【HTML、JAVASCRIPT、CSS】3、Javascript基本概念
基本概念 Javascript是一种基于事件和对象的脚本语言,其特点有:(1)安全性,不允许访问本地硬盘,只做信息的简单动态交互;(2)跨平台性。
749 0
+关注
CtrlX
【个人网站】ctrlx.life 【联系方式】微信:gitctrlx 【软件技能】前端,C++,Python,研究网络工程,数据结构与算法。
31
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载