c++的学习之路:22、多态(1)

这篇具有很好参考价值的文章主要介绍了c++的学习之路:22、多态(1)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

摘要

本章主要是说一些多态的开头。

目录

摘要

一、多态的概念

二、多态的定义及实现

2.1、多态的构成条件

2.2、虚函数

2.3、虚函数的重写

2.4、C++11 override 和 final 

2.5、重载、覆盖(重写)、隐藏(重定义)的对比

三、思维导图


一、多态的概念

多态的概念:通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会
产生出不同的状态。

举个栗子:比如买票这个行为,当普通人买票时,是全价买票;学生买票时,是半价买票;军人买票时是优先买票,这个就很形象,虽然我一次没用过半价车票呜呜,但是这个就是一种多态的体现。

二、多态的定义及实现

2.1、多态的构成条件

多态是在不同继承关系的类对象,去调用同一函数,产生了不同的行为。比如Student继承了Person。Person对象买票全价,Student对象买票半价。那么在继承中要构成多态还有两个条件:

1. 必须通过基类的指针或者引用调用虚函数

2. 被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写

如下方代码就是多态构成实现的代码。

c++的学习之路:22、多态(1),c++,c++,学习,开发语言

class Person
{
public:
    virtual void BuyTicket()
    {
        cout << "买票-全价" << endl;
    }
};
class Student :public Person
{
public:
    virtual void BuyTicket()
    {
        cout << "买票-半价" << endl;
    }
};

void Func(Person& People)
{
    People.BuyTicket();
}

int main()
{
    Person ZhangSan;
    Func(ZhangSan);
    Student LiSi;
    Func(LiSi);
}

2.2、虚函数

虚函数:即被virtual修饰的类成员函数称为虚函数,如下方代码。

class Person {
public:
virtual void BuyTicket() { cout << "买票-全价" << endl;}
};

2.3、虚函数的重写

虚函数的重写(覆盖):派生类中有一个跟基类完全相同的虚函数(即派生类虚函数与基类虚函数的
返回值类型、函数名字、参数列表完全相同),称子类的虚函数重写了基类的虚函数。

注意:在重写基类虚函数时,派生类的虚函数在不加virtual关键字时,虽然也可以构成重写(因为继承后基类的虚函数被继承下来了在派生类依旧保持虚函数属性),但是该种写法不是很规范,不建议这样使用,如下方代码所示。

class Person
{
public:
    virtual void BuyTicket()
    {
        cout << "买票-全价" << endl;
    }
};
class Student :public Person
{
public:
    void BuyTicket()
    {
        cout << "买票-半价" << endl;
    }
};
 

c++的学习之路:22、多态(1),c++,c++,学习,开发语言

虚函数重写的两个例外:

1. 协变(基类与派生类虚函数返回值类型不同)

派生类重写基类虚函数时,与基类虚函数返回值类型不同。即基类虚函数返回基类对象的指针或者引用,派生类虚函数返回派生类对象的指针或者引用时,称为协变,如下方代码所示

class A{};
class B : public A {};
class Person {
public:
virtual A* f() {return new A;}
};
class Student : public Person {
public:
virtual B* f() {return new B;}
};

2. 析构函数的重写(基类与派生类析构函数的名字不同)

如果基类的析构函数为虚函数,此时派生类析构函数只要定义,无论是否加virtual关键字,都与基类的析构函数构成重写,虽然基类与派生类析构函数名字不同。虽然函数名不相同,看起来违背了重写的规则,其实不然,这里可以理解为编译器对析构函数的名称做了特殊处理,编译后析构函数的名称统一处理成destructor。 

注意: 只有派生类Student的析构函数重写了Person的析构函数,下面的delete对象调用析构函
数,才能构成多态,才能保证p1和p2指向的对象正确的调用析构函数,如下方代码所示。

class Person {
public:
    virtual ~Person() { cout << "~Person()" << endl; }
};
class Student : public Person {
public:
    virtual ~Student() { cout << "~Student()" << endl; }
};

int main()
{
    Person* p1 = new Person;
    Person* p2 = new Student;
        delete p1;
    delete p2;
    return 0;
}

c++的学习之路:22、多态(1),c++,c++,学习,开发语言

2.4、C++11 override 和 final 

从上面可以看出,C++对函数重写的要求比较严格,但是有些情况下由于疏忽,可能会导致函数名字母次序写反而无法构成重载,而这种错误在编译期间是不会报出的,只有在程序运行时没有得到预期结果才来debug会得不偿失,因此:C++11提供了override和final两个关键字,可以帮助用户检测是否重写。

1. final:修饰虚函数,表示该虚函数不能再被重写,如下方代码和截图,在在用了final后,后面的就找不到了,显示无法被重写

c++的学习之路:22、多态(1),c++,c++,学习,开发语言

class Person
{
public:
    virtual void BuyTicket() final
    {
        cout << "买票-全价" << endl;
    }
};
class Student :public Person
{
public:
    virtual void BuyTicket()
    {
        cout << "买票-半价" << endl;
    }
}; 

2. override: 检查派生类虚函数是否重写了基类某个虚函数,如果没有重写编译报错如下方代码所示就是没有被重写,会直接报错。

c++的学习之路:22、多态(1),c++,c++,学习,开发语言

class Person
{
public:
    void BuyTicket() 
    {
        cout << "买票-全价" << endl;
    }
};
class Student :public Person
{
public:
    virtual void BuyTicket() override
    {
        cout << "买票-半价" << endl;
    }
}; 

2.5、重载、覆盖(重写)、隐藏(重定义)的对比

如下方图片就是三个概念的对比。

c++的学习之路:22、多态(1),c++,c++,学习,开发语言

三、思维导图

c++的学习之路:22、多态(1),c++,c++,学习,开发语言文章来源地址https://www.toymoban.com/news/detail-851174.html

到了这里,关于c++的学习之路:22、多态(1)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android学习之路(22) 从模块化到组件化

    Android 应用项目 , 都存在一个应用模块 ( Application Module ) , 在 build.gradle 构建脚本中 , 第一个插件配置 com.android.application , 表明 该 Module 编译打包后的输出是 APK 安装包 ; 该项目可以直接运行 ; 如果在 build.gradle 配置的是 com.android.library 插件 , 那么 编译 Module 打包后输出的是 a

    2024年01月22日
    浏览(49)
  • 【C++学习】类和对象--多态【待补充】

    多态是C++面向对象三大特性之一 静态多态:         函数重载和运算符重载属于静态多态,复用函数名(函数地址早绑定,编译阶段确定函数地址) 动态多态:         派生类和虚函数实现运行时多态(函数地址晚绑定,运行阶段确定函数地址)  案例: 输出:  但

    2024年02月02日
    浏览(38)
  • C++类开发第七篇(详细说说多态和编译原理)

    多态性(polymorphism)提供接口与具体实现之间的另一层隔离,从而将”what”和”how”分离开来。多态性改善了代码的可读性和组织性,同时也使创建的程序具有可扩展性,项目不仅在最初创建时期可以扩展,而且当项目在需要有新的功能时也能扩展。 c++支持编译时多态(静态多

    2024年03月09日
    浏览(52)
  • c++入门学习⑦——继承和多态(超级详细版)

    目录 前言 继承 继承是什么? 为什么会存在继承? 语法: 一些基本的定义: 三种继承方式: 对象模型 对于构造和析构的顺序 同名函数的处理方式 总结: 静态成员: 定义: 性质: 共享数据  编译阶段分配内存 类内声明类外初始化 静态成员函数 静态成员函数与普通成员

    2024年02月21日
    浏览(42)
  • 【C++学习】第六章多态与虚函数案例实现

    虚函数的作用就是为了实现多态,和php的延时绑定是一样的。 函数重载是静态的,在横向上的功能, 虚函数是类继承上的功能,是动态的。

    2024年02月09日
    浏览(38)
  • c、c++、java、python、js对比【面向对象、过程;解释、编译语言;封装、继承、多态】

    目录 内存管理、适用 区别 C 手动内存管理:C语言没有内置的安全检查机制,容易出现内存泄漏、缓冲区溢出等安全问题。 适用于系统级编程 C++ 手动内存管理:C++需要程序员手动管理内存,包括分配和释放内存,这可能导致内存泄漏和指针错误。 适用于游戏引擎和系统级编

    2024年02月08日
    浏览(75)
  • NRCE 二级C语言开发环境:Microsoft Visual C++ 2010 学习版下载

    Microsoft Visual C++ 2010 学习版 2022版考纲 网盘链接:点击下载 提取码:siyy 网盘地址下载太慢可以到:官网下载 下载完成后,是一个iso镜像文件,点击上方装载。 装载完成后,可以看到计算机处有个无穷图标的DVD驱动器 现在就可以去到你安装磁盘目录下的IDE目录(星号中间的

    2024年02月11日
    浏览(56)
  • 【C++】多态原理剖析,Visual Studio开发人员工具使用查看类结构cl /d1 reportSingleClassLayout

    author:Carlton tag:C++ topic:【C++】多态原理剖析,Visual Studio开发人员工具使用查看类结构cl /d1 reportSingleClassLayout website:黑马程序员C++ tool:Visual Studio 2019 date:2023年7月24日   目录 父类使用虚函数前后类内部结构变化 子类重写父类虚函数的作用及其机理         首先父类成员

    2024年02月15日
    浏览(74)
  • C语言-学习之路-07

    内存管理 作用域 C语言中变量的作用域可分为:代码作用域、函数作用域、文件作用域 局部变量 局部变量也叫auto自动变量,一般情况下代码块{}内部定义的变量都是自动变量,它有如下特点: 在一个函数内定义,只在函数范围内有效 在复合语句中定义,只在函数范围内有效

    2024年02月03日
    浏览(45)
  • C语言-学习之路-05

    函数 函数分类 C语言程序都是从主函数main()开始执行的。从函数的定义角度看,函数可分为系统函数和用户定义函数。 系统函数(库函数):这是由编译系统提供,用户不必自己定义这些函数,但可以直接使用。例如scanf()、printf()、sizeof()等。 用户定义函数:由用户自行定义

    2024年02月02日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包