多态性是面向对象程序设计的又一个重要思想,关于多态的详尽描述,请看本人的收藏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. 通过Socket让远程电脑执行脚本

    实现功能: 客户端发送命令,服务器接收命令并执行 服务端: import socketserver, os class MyTCPHandler(socketserver.BaseRequestHan ...

  2. Android Studio插件GsonFormat

    GsonFormat插件用于在androidStudio 根据json自动生成class的字段和方法,极大提高了开发效率 一.安装GsonFormat插件 二.重启Android Studio,新建一 ...

  3. c/c++ 标准库 vector

    c/c++ 标准库 vector 标准库 vector的小例子 test1~test7 #include <iostream> #include <vector> using ...

  4. Python的变量以及类型

    1.程序是用来处理数据的,变量就是用来存储数据的  num1 = 100 2.为了更充分的利用内存空间以及更有效率的管理内存,变量是有不同的类型 3.怎样知道一个变量的类型呢? 3.1 在python ...

  5. DELL 服务器报CPU 1 has an internal error (IERR)

    重启服务器,然后按F2 进入到bios中,选择system bios settings这个选项,然后选择system profiles 进入,在这个里面麻烦将 C1E 和Cstate这两个选项改为di ...

  6. SMB协议原理抓包分析

    SMB协议原理抓包分析 目录: 1.SMB概述 2.SMB原理 3.SMB配置 一.SMB概述 SMB(全称是Server Message Block)是一个协议名,可用于在计算机间共享文件.打印机. ...

  7. AndroidNDK开发中使用CMake编译JNI

    虽然一直在做NDK的开发工作,但是由于项目比较久远,都是使用Makefile进行底层编译,对于目前AndroidStudio官方提供的CMake编译方式并不是很了解,现在学习下这种已经不算新潮的新方式 ...

  8. 约瑟夫环简介,问题以及java实现

    问题:一群猴子排成一圈,按1,2,--.,n依次编号.然后从第一只开始数,数到第m只,把它踢出圈,从它后面再开始数,再数到第m只,再把它踢出去-------.,如此不停的进行下去,直到最后只剩下一只猴 ...

  9. ELK收集tomcat状态日志

    1.先查看之前的状态日志输出格式:在logs/catalina.out这个文件中 最上面的日志格式我们可能不太习惯使用,所以能输出下面的格式是最好的,当然需要我们自定义日志格式,接下来看看如何修改 2 ...

  10. 023合并K个链表并排序

    #include "000库函数.h" struct ListNode { int val; ListNode *next; ListNode(int x) : val(x), n ...