C++函数编译原理和成员函数的实现
来源:互联网 发布:区域增长算法 matlab 编辑:程序博客网 时间:2024/06/01 07:39
转载自:http://c.biancheng.net/cpp/biancheng/view/2996.html点击打开链接
从上节的例子可以看出,对象的内存模型中只保留了成员变量,除此之外没有任何其他信息,程序运行时不知道 obj 的类型为 Demo,也不知道它还有一个成员函数 display()。那么,究竟是如何通过对象调用成员函数的呢?
C++函数的编译
C++和C语言的编译方式不同。C语言中的函数在编译时名字不变,或者只是简单的加一个下划线_
(不同的编译器有不同的实现),例如,func() 编译后为 func() 或 _func()。而C++中的函数在编译时会根据命名空间、类、参数签名等信息进行重新命名,形成新的函数名。这个重命名的过程是通过一个特殊的算法来实现的,称为名字编码(Name Mangling)。
Name Mangling 是一种可逆的算法,既可以通过现有函数名计算出新函数名,也可以通过新函数名逆向推演出原有函数名。
Name Mangling 可以确保新函数名的唯一性,只要命名空间、所属的类、参数签名等有一个不同,那么产生的新函数名也不同。
如果你希望看到经算法产生的新函数名,可以只声明而不定义函数,这样调用函数时就会产生链接错误,从报错信息中就可以看到。请看下面的代码:
#include<iostream> using namespace std; void display(); void display(int); namespace ns{ void display(); } class Demo{ public: void display(); }; int main(){ display(); display(1); ns::display(); Demo obj; obj.display(); return 0; }
编译源代码即可看到错误信息:
小括号中就是 Name Mangling 产生的新函数名,它们都以”?“开始,以区别C语言中的”_“。
上图是VS2010产生的错误信息,不同的编译器有不同的 Name Mangling 算法,产生的函数名也不一样。
__thiscall、cdecl 是函数调用方式,有兴趣的读者可以猛击《函数的几种调用方式》一文深入了解。除了函数,某些变量也会经 Name Mangling 算法产生新名字,不再赘述。
成员函数的调用
从上图可以看出,成员函数最终被编译成与对象无关的普通函数,如果函数体中没有成员变量,那问题就很简单,不用对函数做任何处理,直接调用即可。如果成员函数中使用到了成员变量,该怎么办呢?成员变量的作用域不是全局,不经任何处理就无法在函数内部访问。
C++规定,编译成员函数时要额外添加一个参数,把当前对象的指针传递进去,通过指针来访问成员变量。
假设 Demo 类有两个 int 型的成员变量,分别是 a 和 b,并且在成员函数 display() 中使用到了,如下所示:
void Demo::display(){ cout<<a<<endl; cout<<b<<endl; }
void new_function_name(const Demo *p){ //通过指针p来访问a、b cout<<p->a<<endl; cout<<p->b<<endl; }
这样就完成了对象和成员函数的关联,只不过与我们从表明上看到的相反,不是通过对象找函数,而是通过函数找对象。new_function_name(&obj);
这一切都是隐式完成的,对程序员来说完全透明,就好像这个额外的参数不存在一样。
0 0
- C++函数编译原理和成员函数的实现
- CPP中函数编译原理和成员函数的实现
- C++函数编译原理和成员函数的实现
- c++static数据成员和成员函数
- MFC CString类成员函数实现原理
- thinkphp C函数的实现原理
- C++:类的成员函数
- c++-静态成员函数和非静态成员函数的区别
- C++Pirmer 类的成员函数和重载
- 成员变量和成员函数的存储
- C++string类型成员函数实现
- C++之类的成员函数的原理
- C++类成员函数指针和一般函数指针的编译模式的差别
- C++反射类和成员函数的实现
- boost::function(函数)实现普通函数和类成员函数的回调
- C++:如何声明和定义成员函数
- 虚函数和虚析构函数的实现原理
- 混合编译:在c中使用c++中的类对象和类成员函数
- java后台以json字符串的形式,将数据返回给$.ajax的问题总结
- 前台遍历json对象数组
- 如果你用GitHub,可以这样提高效率
- ConcurrentHashMap--锁分段技术
- Eclipse SWT开发教程以及一个连连看游戏的代码实现下载
- C++函数编译原理和成员函数的实现
- ttyS、ttySAC、tty、ttyn的区别
- Java数据类型(上)
- PANIC: ANDROID_SDK_HOME is defined but could not find Test.ini file in $ANDROID_SDK_HOME\.android\av
- CCF ISBN问题
- 点到平面的距离公式推导
- 日期 数字 等的格式转换
- 1008. Elevator (20)
- CodeForces - 367C Sereja and the Arrangement of Numbers (图论&不懂)