前言
本次笔记记录如下知识点
- 成员函数与全局函数调用的区别
- 虚函数与静态成员函数调用的区别
- 静动态类型,绑定,坑点
- 虚析构函数的意义
- RTTI(运行时类型识别)介绍和使用
一、成员函数与全局函数的调用区别
- 编译器内部是将成员函数的调用转换成了一种对全局函数的调用。
- 成员函数被编译器转换为全局函数后,编译器额外增加了一个叫做this的形参,是一个指针类型。该形参对于确定对象所属的某个成员变量在内存中的位置有用。
二、虚函数与静态成员函数调用区别
虚函数的调用方式
- 虚函数的调用分为两种:对象名调用和对象指针调用。
- 对象名调用虚函数就像调用普通成员函数一样,因为这种调用不是多态的,不需要虚函数表。
- 对象指针调用就需要通过虚函数表指针查找到虚函数表,然后通过虚函数表找到要调用的虚函数地址,从而调用指定的虚函数。
通过如下类来进行演示虚函数的调用方式
class A
{
public:
virtual int myfunc1()
{
cout<<"调用虚函数 myfunc1"<<endl;
};
void myfunc2()
{
cout<<"调用虚函数 myfunc2"<<endl;
}
};
通过指针方式调用虚函数
A* a = new A();
a->myfunc1();
在编译器内部会将该a->myfunc1()
代码转换为
- 其中(a)是传入进去的this指针
(* a->vptr[0])(a);
- 在虚函数内部调用虚函数会有两种方式
- 第一种方式是直接编写虚函数名称,如下:
void myfunc2()
{
myfunc1()
cout<<"调用虚函数 myfunc2"<<endl;
}
- 第二中方式是通过类范围操作符来调用,如下:
void myfunc2()
{
A::myfunc1()
cout<<"调用虚函数 myfunc2"<<endl;
}
以上两种调用方式中,第二中的调用方式更加的有效率,因为
A::myfunc1()
这种方式是是鸭子住了虚拟机制,相当于调用一个普通的成员函数。
静态成员函数的调用方式
- 对于静态成员函数的调用,无论用对象名来调用,还是用对象指针来调用,效果都是一样的,都会被编译器转换成一般的针对普通函数(非成员函数)的调用形式。
- 静态成员函数是跟着类走的,所有调用静态成员函数时编译