多态性是面向对象程序设计的又一个重要思想,关于多态的详尽描述,请看本人的收藏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. 洗礼灵魂,修炼python(87)-- 知识拾遗篇 —— 线程(1)

    线程(上) 1.线程含义:一段指令集,也就是一个执行某个程序的代码.不管你执行的是什么,代码量少与多,都会重新翻译为一段指令集.可以理解为轻量级进程 比如,ipconfig,或者, python   ...

  2. SQL Server has encountered 1 occurrence(s) of cachestore flush for the 'Object Plans' cachestore (part of plan cache) due to some database maintenance or reconfigure operations.

    2017-11-01 09:49:44.35 spid166 SQL Server has encountered 1 occurrence(s) of cachestore flush for th ...

  3. [C#]关于路径的几则笔记

    测试环境 本文基于windows下的操作 windows 7 x64 unity 5.3.7p4 获取文件的路径 比如一个文件的路径为:e:\3d\client\trunk\Product\Apps\ ...

  4. Fetch请求后台的数据

    <style> #btn{ width: 50px; height: 50px; background-color: red; } #output{ width: 100px; heigh ...

  5. [福大软工] Z班 团队作业——系统设计 作业成绩

    团队作业--系统设计 作业链接 http://www.cnblogs.com/easteast/p/7709763.html 作业情况 这次作业大家完成度都很高,大家的团队分工,任务布置都安排得很到位 ...

  6. python3编写网络爬虫22-爬取知乎用户信息

    思路 选定起始人 选一个关注数或者粉丝数多的大V作为爬虫起始点 获取粉丝和关注列表 通过知乎接口获得该大V的粉丝列表和关注列表 获取列表用户信息 获取列表每个用户的详细信息 获取每个用户的粉丝和关注 ...

  7. js开发打印证书功能(二)

    在上一篇的基础上,实现了一下另外一种方式. 上一篇地址:https://www.cnblogs.com/ljwsyt/p/9525290.html 首先,该方式也是有几种方法. 1.在上一篇的基础上, ...

  8. Docker for Windows 中文文档(3)——Docker Settings

    Docker设置 Docker运行时,显示Docker鲸鱼. 默认情况下,Docker鲸鱼图标被放置在“通知”区域中. 如果隐藏,单击任务栏上的向上箭头显示. 提示:您可以将鲸鱼固定在通知框外面,使其 ...

  9. 如何设计一个"好的"测试用例?

    什么才算是“好的”测试用例? 好的测试用例一定是一个完备的集合,它能够覆盖所有等价类以及各种边界值,而跟能否发现缺陷无关. "好的"测试用例必须具备哪些特征? 一个“好的”测试用例 ...

  10. UVA1025-A Spy in the Metro(动态规划)

    Problem UVA1025-A Spy in the Metro Accept: 713  Submit: 6160Time Limit: 3000 mSec Problem Descriptio ...