C++中多态实现的关键——虚函数
1.多态的作用
在面向对象程序设计中,使用多态能够增强代码的可扩充性,,即程序需要增加或修改部分功能时,只需修改少量代码就能够达到目的,此外多态也能起到精简代码的作用。
而实现多态的关键点,就是虚函数如何使用。
虚函数
1.虚函数的使用方法
.基同类与派生类同时拥有的同名同参数表的函数,在设计时,最好将其声明为虚函数,只需在函数前面加上关键字virtual即可
下面通过一个具体的例子来说明
#include<iostream>
using namespace std;
class Shape{
public:
void Printf(){
cout<<" The Shape has been called"<<endl;
}
};
class Rectangle:public Shape{
public:
void Printf(){
cout<<"The Rectangle has been called"<<endl;
}
};
class Circle:public Shape{
public:
void Printf(){
cout<<"he Circle has been called"<<endl;
}
};
void Print(Shape &a)
{
a.Printf();
}
void Print(Rectangle &a)
{
a.Printf();
}
void Print(Circle &a)
{
a.Printf();
}
int main()
{
Shape a;
Rectangle b;
Circle c;
Print(a);
Print(b);
Print(c);
return 0;
}
以上程序定义了一个基类Shape 派生出了Rectangle 和 Circle
又定义了三个全局函数用来输出Shape 和Rectangle ,Circle
程序运行结果如下

可以看出三个Print()除了参数,其他完全一样,因此需要一种方法,将Printf()的参数表变得足够灵活,能够同时识别Shape Rectngle Circle
这个时候就可以用到虚函数
具体如下
#include<iostream>
using namespace std;
class Shape{
public:
virtual void Printf(){
cout<<" The Shape has been called"<<endl;
}
};
class Rectangle:public Shape{
public:
void Printf(){
cout<<"The Rectangle has been called"<<endl;
}
};
class Circle:public Shape{
public:
void Printf(){
cout<<"he Circle has been called"<<endl;
}
};
void Print(Shape &a)
{
a.Printf();
}
int main()
{
Shape a;
Rectangle b;
Circle c;
Print(a);
Print(b);
Print(c);
return 0;
}
可以看出,将三个Prinft()函数简化为了一个,而且参数类型为基类的引用
而且在调用时将三种不同的参数类型传入Printf()也不会报错,程序运行结果也是对的
这说明Printf()声明为虚函数后,能够被基类对象正确识别。

并且使用虚函数可以大大简化代码量
2虚函数的识别原理
实际上,对于任何一个含有虚函数,或者其基类含有虚函数的类来说,在其对象的存储空间的最前端,都有一个虚函数表,该虚函数表中存储着该对象的虚函数的地址
多态的函数调用语句被被编译成个根据基类指针或引用所指向的对象中存放的虚函数表的地址,在虚函数表中查询虚函数地址,并调用虚函数的一系列指令

3.虚析构函数
先运行如下程序
#include<iostream>
using namespace std;
class A
{
public:
~A(){
cout<<"A destructor"<<endl;
};
};
class B:public A{
public:
~B(){
cout<<"B destructor"<<endl;
};
};
int main()
{
A *p=new B;
delete p;
return 0;
}

程序的运行结果说明 最后一句delete p,并没有释放掉B的内存,而只释放掉了A的内存,只引发了A的析构函数被调用,被没有调用B的析构函数
这是因为这条语句是静态联编的,编译器进行到delete p 这一句时,并不知道p此时到底指向的是哪个对象,所以只能根据p的类型是A *来调用A的析构函数,
我们希望delete p这样的语句能够足够智能的根据p所指向的对象来执行相应的析构函数
那么将析构函数声明为虚析构函数是一种有效的解决方式
#include<iostream>
using namespace std;
class A
{
public:
virtual ~A(){
cout<<"A destructor"<<endl;
};
};
class B:public A{
public:
~B(){
cout<<"B destructor"<<endl;
};
};
int main()
{
A *p=new B;
delete p;
return 0;
}
将基类析构函数声明为虚函数后
程序运行结果如下

类B的析构函数被正确调用,说明开辟的类B的空间被释放掉
C++中多态实现的关键——虚函数的更多相关文章
- C++中为什么构造函数不能是虚函数,析构函数是虚函数
一, 什么是虚函数? 简单地说,那些被virtual关键字修饰的成员函数,就是虚函数.虚函数的作用,用专业术语来解释就是实现多态性(Polymorphism),多态性是将接口与实现进行分离:用形象的语 ...
- C++基础 (7) 第七天 多态的原理 纯虚函数和抽象类 依赖倒置原则
1 昨日回顾 2 多态的原理 1 要有继承 2 要有子类重写父类的虚函数 3 父类指针(或者引用)指向子类对象 (动态联编 虚函数表 3 证明vptr指针的存在 4 vptr指针在构造父类的时候是分步 ...
- C++中的抽象类及纯虚函数的实现与否
1.含有纯虚函数的叫抽象类 2.抽象类(一般是基类)中的纯虚函数无论函数体实现与否,都没有关系,系统会自动忽略 3.继承自抽象类的子类,必须要实现父类的纯虚函数才可以实例化对象 4.抽象类不允许实例化 ...
- c++ 多态问题(在虚函数里调用虚函数)
最近在看cocos2d-x的源码,非常感激cocos2d作者的开源精神.在看代码的过程中感觉两个方向让我受益,1.把之前从书中看到的c++知识,明白了怎么运用.2.学习作者驾驭代码的巧妙方法. 看co ...
- C++中的多态与虚函数的内部实现
1.什么是多态 多态性可以简单概括为“一个接口,多种行为”. 也就是说,向不同的对象发送同一个消息, 不同的对象在接收时会产生不同的行为(即方法).也就是说,每个对象可 ...
- 详解C++中的多态和虚函数
一.将子类赋值给父类 在C++中经常会出现数据类型的转换,比如 int-float等,这种转换的前提是编译器知道如何对数据进行取舍.类其实也是一种数据类型,也可以发生数据转换,但是这种转换只有在 子类 ...
- C++Review1_多态和虚函数
继承是实现多态的基础.虚函数是实现多态的方法.虚函数.多态.继承都是紧密相关的概念.而继承是所有概念的基础: 多态:简单来讲就是接口一样,实现多样.多态是指通过基类的指针或者引用,在运行时动态调用实际 ...
- 【转载】 C++多继承中重写不同基类中相同原型的虚函数
本篇随笔为转载,原文地址:C++多继承中重写不同基类中相同原型的虚函数. 在C++多继承体系当中,在派生类中可以重写不同基类中的虚函数.下面就是一个例子: class CBaseA { public: ...
- 你好,C++(37)上车的人请买票!6.3.3 用虚函数实现多态
6.3.3 用虚函数实现多态 在理解了面向对象的继承机制之后,我们知道了在大多数情况下派生类是基类的“一种”,就像“学生”是“人”类中的一种一样.既然“学生”是“人”的一种,那么在使用“人”这个概念 ...
随机推荐
- 字节码操作、javassist使用
一.功能 1.动态生成新的类 2.动态改变某个类的结构(添加.删除.修改 新的属性.方法) 二.优势 1.比反射开销小,性能高 2.JAVAasist性能高于反射,低于ASM 使用javassis ...
- clr via c# delegate
1,委托列子 internal delegate void Feedback(int value); class DelegateRef { public static void StaticDele ...
- 小白的linux笔记3:对外联通——开通ssh和ftp和smb共享
1.SSH的开通.https://www.cnblogs.com/DiDiao-Liang/articles/8283686.html 安装:yum install sshd或yum install ...
- P2214 [USACO14MAR]哞哞哞Mooo Moo
链接:Miku ---------------------- 这道题还是个背包 --------------------- 首先看一下声音的组成,对于每一个农场的声音,它是由两部分组成的 :上一个农场 ...
- 【55】目标检测之IOU交并比
交并比(Intersection over union) 你如何判断对象检测算法运作良好呢?在本笔记中,你将了解到并交比函数,可以用来评价对象检测算法.在下一个笔记中,我们用它来插入一个分量来进一步改 ...
- 广度优先搜索BFS---求出矩阵中“块”的个数
题目: 给出一个 m x n 的矩阵,矩阵中的元素为0或1.如果矩阵中有若干个 1是相邻的,那么称这些1构成了一个“块”.求给定的矩阵中“块”的个数. 0 1 1 1 0 0 1 0 0 1 0 0 ...
- grep 基本用法
grep usage: grep [options]... pattern [file]... 如果file缺省,会从 stdin 读取 $ grep --help -i 忽略大小写 -n 显示行号 ...
- 小程序上拉触底&下拉加载
data: { pageNo: 1,//当前页 pageSize: 10,//每页条数 count:'',//总条数 orderList: [], }, onLoad: function () { v ...
- fatal error LNK1169: one or more multiply defined symbols found
在 Project/Setting/Link/General中的 Project Options: 加入 /FORCE:MULTIPLE即可")可以解决报错问题,但是这些问题全部变成了war ...
- Beamer加入背景图片
在Beamer中加入背景图片只要把背景重新设置一下: \setbeamertemplate{background}{\includegraphics[height=\paperheight]{bg}} ...