腾讯广告建站工具,哪个网站做马代路线好,杭州做邮票的公司网站,网站优化合同1、普通成员函数的调用
1.1 调用方式的转换
为了提高普通成员函数的调用效率#xff0c;在C中#xff0c;对普通成员函数的调用#xff0c;会转换成对全局函数的调用。
假如有下面所示的成员函数#xff1a;
class Test {
public:int m_i;int func(int a) {m_i a;retu…1、普通成员函数的调用
1.1 调用方式的转换
为了提高普通成员函数的调用效率在C中对普通成员函数的调用会转换成对全局函数的调用。
假如有下面所示的成员函数
class Test {
public:int m_i;int func(int a) {m_i a;return m_i;}
};
在编译时会经历下面几个步骤
1把对象的首地址作为参数传递给函数。
int func(Test *const this, int a) {}
2对非静态成员变量的调用改成通过this指针来调用。
int func(Test *const this, int a) {this-m_i a;return this-m_i;
}
3对函数名进行name mangling操作通过函数名和其参数类型生成唯一标识符来区分不同的函数。
int _ZN4Test4funcEi(Test *const this, int a){}
1.2 代码演示
1
在main()函数中加入调用函数func()的代码
int main() {Test test;int ret test.func(6);
}
然后把断点设在int ret test.func(6); 运行程序后查看反汇编代码VS2019 简单分析下汇编语言的意思
1push 6把参数6入栈。
2lea ecx, [test]把test写入ecx。
这2行其实是参数传递。
3call Test::func(05C12D0h)调用函数func。
4move dword ptr [ret], eax把eax的值赋给ret。
从这些代码可以看到函数的调用流程可分成3个阶段参数传递、调用函数call、处理返回值。
在反汇编的“地址(A)”窗口输入函数func的地址05C12D0h回车后查看函数func的反汇编代码 这段汇编的细节不去深究但我们可以看到有[this]字样可以知道函数在具体执行时用到了this指针。
所以对func函数的调用转换可以用下图表示 如果用指针方式调用成员函数
Test* pTest;
int ret pTest-func(6);
则对func函数的调用转换是这样的 2把代码在linux上编译后用nm命令查看可执行文件的信息。
linux下编译g ch19.cpp -o ch19
用nm命令查看可执行文件nm ch19 可以看到func函数被转换成了_ZN4Test4funcEi。
2、静态成员函数的调用
对于静态成员函数的调用无论用对象名来调用还是用对象指针来调用效果都是一样的都会被编译器转换成一般的针对普通函数非成员函数的调用形式。
静态成员函数是跟着类走的所有调用静态成员函数时编译器是不会插入this作为形参的。
假如类Test有一个static成员函数
static void stfunc() { }
则可以用下面的方法来调用此静态成员函数
Test test;
test.stfunc();Test::stfunc();Test* pTest;
pTest-stfunc();
静态成员函数有以下特点
1静态成员函数没有this指针这点最重要。
2无法直接存取类中普通的非静态成员变量因为非静态成员变量是通过this指针来操作的。
3静态成员函数不能在后面使用const也不能设置为virtual。
4可以用类对象调用但不非一定要用类对象调用。
5静态成员函数等同于非成员函数需要提供回调函数的这种场合可以将静态成员函数作为回调函数。