虚函数 静态绑定 动态绑定

虚函数详解: https://blog.csdn.net/lyztyycode/article/details/81326699

虚函数作用主要是实现了多态机制多态就是用父类类别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。这种技术可与让父类的指针有"多种形态"。(这是一种泛型技术。所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法。比如:模板技术,RTTI技术,虚函数技术,要么是试图做到在编译时决议,要么试图做到运行时决议。)

   

C++虚函数&静态绑定和动态绑定-vfptr虚函数指针-vftable虚函数表

https://www.bilibili.com/video/BV1MP4y1Y7qQ?spm_id_from=333.851.header_right.history_list.click

   

判断是不是动态绑定,就看定义为父类的指针 指的函数是不是虚函数,并且改指针指向子类 的函数是否重写(覆盖)

   

一个类定义了虚函数,对类有什么影响

总结一:如果类里面定义了虚函数,那么编译器需给这个类型产生一个唯一的vftable虚函数表,虚函数表中主要存储的内容就是RTTI(运行时的类型信息)指针虚函数的地址。当程序运行时,每一张虚函数表都会加载到内存的.rodata区(只读不能写)

   

总结二:一个类里面定义了虚函数,那么这个类定义的对象,在其运行时,内存中开始部分,多存储一个vfptr虚函数指针,指向相应类型的虚函数表vftable。一个类型定义的n个对象,他们的vfptr指向的都是同一个虚函数表

   

总结三:一个类里面虚函数的个数不影响对象内存大小(vfptr),影响的是虚函数表的大小

   

总结四:如果派生类中的方法,和基类继承来的某个方法,函数名,参数列表,返回值都相同,而且基类的方法是vritual虚函数,那么派生类的这个方法自动处理为虚函数。(覆盖的关系)

静态绑定:

   

#include <iostream>

using namespace std;

   

class Base {

public:

int ma;

public:

Base(int data = 10) : ma (data) {}

//非虚函数

void show() {

cout << "Base::show()" << endl;

}

//非虚函数

void show(int data) {

cout << "Base::show(int)" << data << endl;

}

};

   

class Son : public Base {

public:

int mb;

public:

Son(int data = 100) : mb(data) {}

void show() {

cout << "Son::show()" << endl;

}

};

   

int main() {

Son s = Son();

Base* p = &s;

   

p->show();        //Base::show()                静态绑定,编译期绑定,运行父类函数

p->show(1);        //Base::show(int)1        静态绑定,编译期绑定,运行父类函数

   

return 0;

}

动态绑定:

   

#include <iostream>

using namespace std;

   

class Base {

public:

int ma;

public:

Base(int data = 10) : ma (data) {}

//虚函数

virtual void show() {

cout << "Base::show()" << endl;

}

//虚函数

virtual void show(int data) {

cout << "Base::show(int)" << data << endl;

}

};

   

class Son : public Base {

public:

int mb;

public:

Son(int data = 100) : mb(data) {}

//对父类函数进行了重写

//虚函数表放的是不是父类函数的地址,而是重写后的函数地址

void show() {

cout << "Son::show()" << endl;

}

};

   

int main() {

Son s = Son();

Base* p = &s;

   

//Base::show() 是一个虚函数 而且子类进行了重写 进行动态绑定

p->show();        //Son::show()                动态绑定,运行时期的绑定,运行子类函数

p->show(1);        //Base::show(int)1        静态绑定,编译期的绑定,运行父类函数

   

return 0;

}

重写(覆盖):

虚函数表中虚函数地址的覆盖

   

父类base 虚函数表

   

子类 虚函数表:

重写(覆盖):虚函数表中虚函数地址的覆盖

posted @ 2022-08-30 21:11  atomxing  阅读(98)  评论(0编辑  收藏  举报