C++中虚函数的动态绑定和多态性
目录
- 静态类型 vs 动态类型、静态绑定 vs 动态绑定
- 虚函数动态绑定实现机制、虚析构函数
- 多态性
一.静态 vs 动态
静态类型 VS 动态类型。静态类型指的是对象声明的类型,在编译器确定的。动态类型指的是对象的所指向的类型,动态类型是可以更改的,静态类型无法更改。继承关系会导致对象的指针和引用具有静态类型和动态类型,因为继承关系的存在中可能会存在类型之间的向上向下类型转换。静态绑定 VS 动态绑定。某特性(函数)依赖与对象的静态类型,在编译期确定,某特性(函数)依赖于对象的动态类型,在运行期确定。只有通过基类的引用或者指针调用虚函数时,才能发生动态绑定,如果使用对象来操作虚函数的话,仍然会采用静态绑定的方式。因为引用或者指针既可以指向基类对象,也可以指向派生类对象的基类部分,用引用或者指针调用的虚函数。例如下面的例子中,pd的静态类型是D*,pb的静态类型是B*,是在编译器确定的;pd和pb的动态类型都是D*。DoSomething()普通的成员函数是在编译器静态绑定的,调用各自的静态类型中的方法。vfun()是虚成员函数,虚函数是动态绑定的,因此调用动态类型的方法,也就是D类型中vfun。
#include <iostream>
using namespace std; class B
{
public:
void DoSomething(){
std::cout << "B::DoSomething()" << endl;
}
virtual void vfun(){
std::cout << "B::vfun()" << endl;
}
}; class D : public B
{
public:
void DoSomething(){
std::cout << "D::DoSomething()" << endl;
}
virtual void vfun(){
std::cout << "D::vfun()" << endl; }
}; int main()
{
D* pd = new D(); //指针存在注意静态类型和动态类型
B* pb = pd; //指正注意静态类型和动态类型
pd->DoSomething(); //普通成员函数,静态绑定静态类型中的方法
pb->DoSomething(); //普通成员函数,静态绑定静态类型中的方法 pd->vfun(); //虚成员函数,动态绑定到动态类型中的方法
pb->vfun(); //虚成员函数,动态绑定到动态类型中的方法
return ;
}
二.虚函数动态绑定的实现机制
对象的指针或者引用调用虚函数的行为是动态绑定。虚函数是通过虚函数表来实现的。对于每一个含有虚函数的类,编译器会为其创建一个虚函数表Vtable,虚函数表中记录JMP指令的地址。类的虚函数表被该类的所有对象共享,编译器会为每个虚函数的实例分配指向该类的虚函数表的指针。当一个含有虚成员函数的类被继承后,器派生类中的同名函数会自动的成为虚函数,因此子类在重写这个虚函数时,可以添加,也可以不加virtual关键字,习惯上会加上virtual使得程序更加的清晰。父类指针调用虚成员函数是多态在代码层面的体现,这在运行过程中,父类指针将动态绑定(关联)到具体的某个虚函数。指的是在运行期根据父类指针的动态类型的虚函数表来绑定到具体的函数。含有虚函数的类记住使用虚析构函数,否则容易导致派生类的资源无法正常释放。例如下面情况。如果想进一步了解虚函数表需要了解,C++的对象模型,建议查看《C++中对象模型》。
#include <iostream>
using namespace std; class B
{
public:
void DoSomething(){
std::cout << "B::DoSomething()" << endl;
}
virtual void vfun(){
std::cout << "B::vfun()" << endl;
} ~B(){
std::cout << "~B()" << std::endl;
}
}; class D : public B
{
public:
void DoSomething(){
std::cout << "D::DoSomething()" << endl;
}
virtual void vfun(){
std::cout << "D::vfun()" << endl; }
~D(){
std::cout << "~D()" << std::endl;
}
}; int main()
{
B* pb = new D();
pb->vfun();
delete pb; // ~B();
return ;
}
三 C++多态性体现
C++多态性代码层面体现的是父类的指针或引用调用虚成员函数。多态产生有三个条件:产生的条件是继承关系、基类中含有虚成员函数、派生类重写基类的虚成员函数。当用父类指针或引用调用虚成员函数,这个调用关系在运行器可能绑定(关联)到不同的子类,产生不同的行为。
#include <iostream>
using namespace std;
class Person
{
public:
virtual void print(){
std::cout << "I'm a person" << endl;
}
virtual void foo(){}
}; class Chinese : public Person
{
public:
virtual void print(){
std::cout << "I'm as Chinese" << endl;
}
virtual void foo2(){}
};
class American : public Person
{
public:
virtual void print(){
std::cout << "I'm as American" << endl;
}
};
//reference
void printPerson(Person& person){
person.print();
}
//pointer
void printPerson(Person* p){
p->print();
}
int main()
{
Person p;
Chinese c;
American a;
printPerson(&p);
printPerson(&c);
printPerson(&a);
return ;
}
C++中虚函数的动态绑定和多态性的更多相关文章
- C++入门经典-例8.7-多态,利用虚函数实现动态绑定
1:多态性是面向对象程序设计的一个重要特征,利用多态性可以设计和实现一个易于扩展的系统.在C++语言中,多态是指具有不同功能的函数可以用同一个函数名,这样就可以用一个函数名调用不同内容的函数,发出同样 ...
- C++中虚函数的作用浅析
虚函数联系到多态,多态联系到继承.所以本文中都是在继承层次上做文章.没了继承,什么都没得谈. 下面是对C++的虚函数这玩意儿的理解. 一, 什么是虚函数(如果不知道虚函数为何物,但有急切的想知道,那你 ...
- C++中虚函数的作用是什么?它应该怎么用呢?(转)
虚函数联系到多态,多态联系到继承.所以本文中都是在继承层次上做文章.没了继承,什么都没得谈. 下面是对C++的虚函数这玩意儿的理解. 一, 什么是虚函数(如果不知道虚函数为何物,但有急切的想知道,那你 ...
- c++中虚函数
虽然很难找到一本不讨论多态性的C++书籍或杂志,但是,大多数这类讨论使多态性和C++虚函数的使用看起来很难.我打算在这篇文章中通过从几个方面和结合一些例子使读者理解在C++中的虚函数实现技术.说明一点 ...
- C++中虚函数的作用和虚函数的工作原理
1 C++中虚函数的作用和多态 虚函数: 实现类的多态性 关键字:虚函数:虚函数的作用:多态性:多态公有继承:动态联编 C++中的虚函数的作用主要是实现了多态的机制.基类定义虚函数,子类可以重写该函数 ...
- 关于C++与Java中虚函数问题的读书笔记
之前一直用C++编程,对虚函数还是一些较为肤浅的理解.可近期由于某些原因搞了下Java,发现有些知识点不熟,于是站在先驱巨人的肩上谈谈C++与Java中虚函数问题. Java中的虚函数 以下是段别人的 ...
- C++中虚函数功能的实现机制
要理解C++中虚函数是如何工作的,需要回答四个问题. 1. 什么是虚函数. 虚函数由于必须是在类中声明的函数,因此又称为虚方法.所有以virtual修饰符开始的成员函数都成为虚方法.此时注意是vir ...
- c++中虚函数和多态性
1.直接看下列代码: #include <iostream> using namespace std; class base{ public: void who(){ cout<&l ...
- C++中虚函数的作用
一, 什么是虚函数(如果不知道虚函数为何物,但有急切的想知道,那你就应该从这里开始) 简单地说,那些被virtual关键字修饰的成员函数,就是虚函数.虚函数的作用,用专业术语来解释就是实现多态性(Po ...
随机推荐
- H3C交换机流量镜像
今天需要对交换机进行本地流量镜像,在此记录: 交换机:H3C S5120 配置本地端口镜像时,用户首先要创建一个本地镜像组,然后为本地镜像组配置源端口和目的端口. 表1-1 配置本地端口镜像 操作 命 ...
- 99 Times--Kate Voegele
歌手 Kate Voegele 是美国俄亥俄州的一位年轻创作型歌手,她会唱歌.会写歌.特 别擅长弹吉他.还会弹钢琴.她是美国新生代歌手中的佼佼者. 99 Times--Kate Voegele S ...
- Sublime Text 3 格式化HTML CSS JS 代码
一,首先通过ctrl+shift+p 要等一会就会出现插件安装界面 二,在插件安装输入框,输入:HTML-CSS-JS Prettify 并安装该插件 三,如果没有装nodejs, 下载nodejs ...
- html隐藏元素
<body> <div>display:元素的位置不被占用</div> <div id="div1" style="displa ...
- SQL导入的方法,网上看到的
-------这是一个新表,准备用来导入的表 CREATE TABLE CSVTable( Name NVARCHAR(MAX), Email NVARCHAR(MAX), Area NVARCHAR ...
- linux 下mysql/php编译配置参数
mysql cmake 编译参数 cmake -DCMAKE_INSTALL_PREFIX=/opt/mysql \-DSYSCONFDIR=/opt/mysql/etc \-DMYSQL_DATAD ...
- “System.Runtime.InteropServices.COMException”类型的第一次机会异常在 System.Windows.Forms.dll 中发生
最近做一个winform项目,在里面用了webbrowser控件进行html文档打印,遇到了标题所示问题.根据查到的一些资料,在调试>异常>查找中输入“System.Runtime.Int ...
- Day6 ,周期末考试试题
Python基础数据类型考试题 考试时间:两个半小时 满分100分(80分以上包含80分及格) 一,基础题. 1,简述变量命名规范(3分) 2,字节和位的关系 ...
- 201621123018《Java程序设计》第2周学习报告
Week02-Java基本语法与类库 1.本周学习总结 Java数据类型分为基本数据类型和引用数据类型.布尔型是Java特有的数据类型.本周重点学习了字符串类型String,String类型中==和e ...
- Axure学习了解
我这次介绍的原型设计工具为Axure 一.区域介绍 这是主界面: 左上区域显示原型的各个界面,可以添加新界面: 左中包含各种原型设计所包含的组件,例如文本框,图片等: 左下是各种模板,模板由自己设计, ...