多态性是面向对象程序设计的又一个重要思想,关于多态的详尽描述,请看本人的收藏https://www.cnblogs.com/hust-ghtao/p/3512461.html。这篇博文中,详尽的探讨了多态的一些特性。

在此,我仅仅以白话的方式描述为何要引入多态:

子类继承了基类的方法,但子类可以改变这些这些方法以适应自己的特性,而不是只能照搬基类的方法。现在面临这样一个问题:访问的便捷性和权限。

我们可以使用对象名的方式来访问方法,或者使用类指针,类引用的方式来访问,这都是完全OK的。关键问题在于,假如我们有很多派生子类,比如1000个,当我们要访问具有类似功能(但又有所差异的)的接口时,难道还要用很多对象名去访问吗?显然不科学,一方面,我们这样做,使得程序缺乏灵活性,易读性,还费时费力。

那么有没有一种方法使得我们能够用一种统一的方式来进行这种访问呢?有的,那就是虚函数。

见一段代码:

 # include "iostream"
using namespace std;
class Base
{
public:
void funpublic()
{
cout << "基类的成员函数" << endl;
}
}; class child1 :public Base
{
public:
void funpublic()
{
cout << "派生类child1的成员函数" << endl;
}
}; class child2 :public Base {
public:
void funpublic()
{
cout << "派生类child2的成员函数" << endl;
}
};
int main() {
Base * p1, *p2, *p3, base;//假如在基类中不使用虚函数,则当我们定义一个基类指针时,就注定我们所访问的方法就是基类方法,但如果我们想访问派生类方法,就
//没有这个访问权限;但若我们定义派生类指针,则只能够指向某一个派生类,无法指向其他派生类(包括基类)。但程序初衷是:设计一种方式
//这种方式能够访问基类和派生类中方法相同(实现方式有所差异)的接口,能够随着我们所调用的对象的所属类,自动调用相应的方法(如果有)
//这时,就要采用相应的虚函数的方法。
child1 obj1;
child2 obj2;
base = obj1;
base.funpublic();
Base &aliasbase = obj2;
aliasbase.funpublic();
p1 = &obj1;
p2 = &obj2;
p1->funpublic();
p2->funpublic();
p2 = new child1;
p2->funpublic();
p3 = new child2;
p3->funpublic();
system("pause");
return ;
}

上述这段代码中没有使用虚函数,我们看一下结果:

我们本意是试图通过指针去访问子类的方法,但是失败了,原因是:倘若我们偷懒,想只定义一个基类指针,就能完成对所有子类同一方法的访问,但是很明显,基类指针不具备这样的访问权限,也就是,当我们定义一个基类指针时,就注定了我们基类指针所指向的对象的指针(这里应该叫地址)会被转化为基类的地址,也就是,我们没有办法去访问真正意义上的派生类指针,当然,我们定义一个派生类指针,也不能够访问其他派生类的方法,当然,更不能访问基类方法。

那么有没有一种方法,能够帮助我们一劳永逸,只定义一个指针就能访问其他所有派生类同名方法呢?有的

 # include "iostream"
using namespace std;
class Base
{
public:
virtual void funpublic()
{
cout << "基类的成员函数" << endl;
}
}; class child1 :public Base
{
public:
void funpublic()
{
cout << "派生类child1的成员函数" << endl;
}
}; class child2 :public Base {
public:
void funpublic()
{
cout << "派生类child2的成员函数" << endl;
}
};
int main() {
Base * p1, *p2, *p3, base;//假如在基类中不使用虚函数,则当我们定义一个基类指针时,就注定我们所访问的方法就是基类方法,但如果我们想访问派生类方法,就
//没有这个访问权限;但若我们定义派生类指针,则只能够指向某一个派生类,无法指向其他派生类(包括基类)。但程序初衷是:设计一种方式
//这种方式能够访问基类和派生类中方法相同(实现方式有所差异)的接口,能够随着我们所调用的对象的所属类,自动调用相应的方法(如果有)
//这时,就要采用相应的虚函数的方法。
child1 obj1;
child2 obj2;
base = obj1;
base.funpublic();
Base &aliasbase = obj2;
aliasbase.funpublic();
p1 = &obj1;
p2 = &obj2;
p1->funpublic();
p2->funpublic();
p2 = new child1;
p2->funpublic();
p3 = new child2;
p3->funpublic();
system("pause");
return ;
}

这段代码与前面一段代码仅仅多了一个关键字,但是结果大不相同:

可见,当我们将类方法声明为虚方法的时候,大大提高了基类指针的访问权限,使得基类指针能够真正意义上访问子类方法,因此,使用虚函数的方法实现多态是一种优秀的程序设计理念。

关于虚函数和多态细节信息请见我开篇转载博客。

实际上,了解虚函数的本质和核心原理有助于我们更好的驾驭虚函数的使用,这篇博文中作者以精辟的手法,描述了虚函数的核心机制:https://blog.csdn.net/neiloid/article/details/6934135

C++入门之初话多态与虚函数的更多相关文章

  1. 《挑战30天C++入门极限》C++中类的多态与虚函数的使用

        C++中类的多态与虚函数的使用 类的多态特性是支持面向对象的语言最主要的特性,有过非面向对象语言开发经历的人,通常对这一章节的内容会觉得不习惯,因为很多人错误的认为,支持类的封装的语言就是支持 ...

  2. C++中的多态与虚函数的内部实现

    1.什么是多态         多态性可以简单概括为“一个接口,多种行为”.         也就是说,向不同的对象发送同一个消息, 不同的对象在接收时会产生不同的行为(即方法).也就是说,每个对象可 ...

  3. C++多态、虚函数、纯虚函数、抽象类、虚基类

    一.C++多态 C++的多态包括静态多态和动态多态.静态多态包括函数重载和泛型编程,动态多态包括虚函数.静态多态是指在编译期间就可以确定,动态多态是指在程序运行时才能确定. 二.虚函数 1.虚函数为类 ...

  4. C++多态、虚函数、纯虚函数、抽象类

    多态 同一函数调用形式(调用形式形同)可以实现不同的操作(执行路径不同),就叫多态. 两种多态: (1)静态多态:分为函数重载和运算符重载,编译时系统就能决定调用哪个函数. (2)动态多态(简称多态) ...

  5. [c++] C++多态(虚函数和虚继承)

    转自:https://www.jianshu.com/p/02183498a2c2 面向对象的三大特性是封装.继承和多态.多态是非常重要的一个特性,C++多态基于虚函数和虚继承实现,本文将完整挖掘C+ ...

  6. C++中类的多态与虚函数的使用

    C++的三大特性:封装.继承.多态.以前学的时候自己没去总结,记得在一本c++入门的书讲得还是比较清楚.今天上网找了一下多态,找到下面这篇文章写得比较清晰. http://pcedu.pconline ...

  7. C++ 多态与虚函数

    1.多态的概念 由虚函数实现的动态多态性就是:同一类族中不同类的对象,对同一函数调用作出不同的响应. 先看下面这个简单的例子: #include<iostream> using std:: ...

  8. C++多态,虚函数,虚函数表,纯虚函数

    1.多态性   指相同对象收到不同消息或不同对象收到相同消息时产生不同的实现动作. C++支持两种多态性:编译时多态性,运行时多态性.    a.编译时多态性:通过重载函数实现 ,模板(2次编译)  ...

  9. C++类、继承、多态、虚函数

    一个比较好的虚函数例子 /****************************/ /* 作者:骆天 */ /* 时间:2018/1/26 */ /* 代码:多态的理解 */ /********** ...

随机推荐

  1. 在微信小程序中使用LeanCloud(一)

    之前学习了微信小程序前端,使用到LeanCloud线上数据库 [传送门].作为一个前端开发人员,了解后端及数据库是学习工作的需要. LeanCloud直接登录,未注册直接创建账户.它是一款免费的线上数 ...

  2. 一套简单的git版本控制代码

    对于博客来说,我还是直接实践比较好,理论过多,不方便以后的查看 废话不多,直接开干 功能需求: .公司需要将jenkins打包出来的压缩包通过git上传到git服务器 .而且通过版本控制上传的文件,即 ...

  3. 记一次 MySQL semaphore crash 的分析(爱可生)

    文章来源:爱可生云数据库作者:洪斌 DBA应该对InnoDB: Semaphore wait has lasted > 600 seconds. We intentionally crash t ...

  4. Linux下键盘值 对应input_evnet的code值。

    最近做了一个linux下面的模拟鼠标和键盘的app,但不是很清楚字符对应的键值:查找内核源码,在kernel/include/uapi/linux/input.h文件中找到: 下面给出普通键盘上面对应 ...

  5. 【NOI2018模拟5】三角剖分Bsh

    [NOI2018模拟5]三角剖分Bsh Description 给定一个正 n 边形及其三角剖分,共 2n - 3 条边 (n条多边形的边和n-3 条对角线),每条边的长度为 1. 共 q 次询问,每 ...

  6. Linux之特殊符号与正则表达式

    Linux中常用的特殊符号 '' 所见即所得,吃啥吐啥 "" 特殊符号会被解析运行 `` ==== $() 先运行里面的命令 把结果留下 > 重定向符号 先清空文件的内容 然 ...

  7. Request Body可以反复读取的方法

    org.springframework.web.filter.HiddenHttpMethodFilter:过滤器已经读取流了,因此想频繁读取流的话,自定义Filter必须在org.springfra ...

  8. 使用ECharts来实现地图下钻功能(某省的市级下钻到县级)

    var cityMap = { "长沙市": "430100", "株洲市": "430200", "湘潭市& ...

  9. [LeetCode]最大系列(最大正方形221,最大加号标志764)

    221. 最大正方形 题目描述: 在一个由 0 和 1 组成的二维矩阵内,找到只包含 1 的最大正方形,并返回其面积. 示例: 输入: 1 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 ...

  10. ③---Java项目管理工具MAVEN安装与配置

    Java项目管理工具MAVEN安装配置以下将为大家介绍Java项目管理工具MAVEN安装及其配置. 一.下载MAVEN安装文件 maven下载地址:https://maven.apache.org/d ...