C++入门之初话多态与虚函数
多态性是面向对象程序设计的又一个重要思想,关于多态的详尽描述,请看本人的收藏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++入门之初话多态与虚函数的更多相关文章
- 《挑战30天C++入门极限》C++中类的多态与虚函数的使用
C++中类的多态与虚函数的使用 类的多态特性是支持面向对象的语言最主要的特性,有过非面向对象语言开发经历的人,通常对这一章节的内容会觉得不习惯,因为很多人错误的认为,支持类的封装的语言就是支持 ...
- C++中的多态与虚函数的内部实现
1.什么是多态 多态性可以简单概括为“一个接口,多种行为”. 也就是说,向不同的对象发送同一个消息, 不同的对象在接收时会产生不同的行为(即方法).也就是说,每个对象可 ...
- C++多态、虚函数、纯虚函数、抽象类、虚基类
一.C++多态 C++的多态包括静态多态和动态多态.静态多态包括函数重载和泛型编程,动态多态包括虚函数.静态多态是指在编译期间就可以确定,动态多态是指在程序运行时才能确定. 二.虚函数 1.虚函数为类 ...
- C++多态、虚函数、纯虚函数、抽象类
多态 同一函数调用形式(调用形式形同)可以实现不同的操作(执行路径不同),就叫多态. 两种多态: (1)静态多态:分为函数重载和运算符重载,编译时系统就能决定调用哪个函数. (2)动态多态(简称多态) ...
- [c++] C++多态(虚函数和虚继承)
转自:https://www.jianshu.com/p/02183498a2c2 面向对象的三大特性是封装.继承和多态.多态是非常重要的一个特性,C++多态基于虚函数和虚继承实现,本文将完整挖掘C+ ...
- C++中类的多态与虚函数的使用
C++的三大特性:封装.继承.多态.以前学的时候自己没去总结,记得在一本c++入门的书讲得还是比较清楚.今天上网找了一下多态,找到下面这篇文章写得比较清晰. http://pcedu.pconline ...
- C++ 多态与虚函数
1.多态的概念 由虚函数实现的动态多态性就是:同一类族中不同类的对象,对同一函数调用作出不同的响应. 先看下面这个简单的例子: #include<iostream> using std:: ...
- C++多态,虚函数,虚函数表,纯虚函数
1.多态性 指相同对象收到不同消息或不同对象收到相同消息时产生不同的实现动作. C++支持两种多态性:编译时多态性,运行时多态性. a.编译时多态性:通过重载函数实现 ,模板(2次编译) ...
- C++类、继承、多态、虚函数
一个比较好的虚函数例子 /****************************/ /* 作者:骆天 */ /* 时间:2018/1/26 */ /* 代码:多态的理解 */ /********** ...
随机推荐
- 验证对Random的两个猜想
猜想1:Random.Next()产生的随机数不会有重复. 猜想2:大量级执行Random.Next(int i)分布在各个数值上的概率是均匀的. 验证猜想1 /*如果Random.Next()产生的 ...
- C#中ExecuteReader、ExecuteNonQuery、ExecuteScalar、SqlDataReader、SqlDataAdapter应该怎么用?
C#中ExecuteReader.ExecuteNonQuery.ExecuteScalar.SqlDataReader.SqlDataAdapter应该怎么用? (2013-10-16 13:21: ...
- 老K漫谈区块链的共识(1)——免信任的共识机制
老k,柏链道捷CTO.清华阿尔山区块链研究中心高级工程师,超过17年的系统软件开发经验,在操作系统.编译器.虚拟机和符号执行方面都有实战经验.主持开发多个开眼项目,目前主要从事区块链底层系统开发工作. ...
- Linux文件管理命令 cat
1.cat 命令:将文件内容连接后传送到标准输出或重定向到文件. 1)命令语法格式:cat [OPTION] [FILE]... 2)命令选项参数说明如下所示. -n(number):从第一行开始对文 ...
- openSUSE Leap 15.0 Adobe Flash Player 安装说明
鉴于Firefox安装配置文件: mozilla_lib=file $MOZ_PROGRAM LIB=lib -bit.*(x86-|S/|PowerPC|ARM aarch64)’ &&am ...
- Boolean类型在EF和MySql中的映射关系
MySQL没有Boolean类型.这也是比较奇怪的现象.例: create table xs ( id int primary key, bl boolean ) 这样是可以创建成功,但查看一下建表后 ...
- Nginx使用教程(三):Nginx配置性能优化之I/O和TCP配置
配置Nginx I/O <br\> Sendfile 当应用程序传输文件时,内核首先缓冲数据,然后将数据发送到应用程序缓冲区. 应用程序反过来将数据发送到目的地. Sendfile方法是一 ...
- Java面试知识点之计算机网络篇(一)
前言:在Java面试中,计算机网络的知识也是一项重点,因此笔者在此对计算机网络的相关知识进行总结. 1.OSI参考模型 自下而上:物理层(物理介质,比特流).数据链路层(网卡.交换机).网络层(IP协 ...
- C#のsocket通信
博主要做一个手机和电脑端(C#)通讯的程序,便览了网络上关乎socket的东西.但是接收文件的时候卡住了,怎么也接收不全.后来做了分片处理,如果分片,发送的时候就会有不同的socket(客户端开发不是 ...
- 修改CentOS默认yum源为国内yum镜像源
CentOS默认的yum源不是国内的yum源,在通过yum安装一些软件的时候,会出现这样那样的错误,以及在下载安装的速度上也是非常慢的. 所以这个时候就需要将yum源替换成国内的yum源,国内主要开源 ...