9.5 实现依赖性
当然,C++(www.cppentry.com)语言定义并没有陈述任何关于语言应该如何实现的问题(ARM确实给出了许多广泛用于实现的技术,但所有这些技术都不是强制要求的)。因此,那些旨在编写可移植代码的程序员应该避免依赖于某个特殊的C++(www.cppentry.com)实现的细节。
为了理解程序员为何会热衷于依赖语言的实现细节,我们考虑下面这个例子:
- f.c
- void f(int i){
- //...
- }
- void f(char c){
- //...
- }
- main:c:
- void f(int);
- void f(char);
- int main(){
- f(0);
- f('0');
- //...
- }
当链接这个程序的时候,main.c中每个f函数的引用都会调用定义在f.c中相应的实例。为了确保实际情况确实如此,现今所有C++(www.cppentry.com)编译器都在目标代码中,把参数类型编码(代码化)到函数的名称中。例如,C++(www.cppentry.com)实现可能会使用编码后的名字f__Fi和f__Fc分别代表f(int)和f(char)。编码化后的函数名称也会随着编译系统的不同而各不相同,甚至由于系统版本的差异也会带来一些差异。因此,对于那些依赖于这类名称编码机制的程序员,编写出来的代码将是不可移植代码。
然而,假设我们的编译器会由于创建两个f函数的定义,而变得异常低效;并且假设我们知道如何在其他的语言(如C)编写更加高效的代码;那么我们可能会用下面的C代码来取代f.c中的定义:
- /*c代码*/
- void f__Fi(int i){
- /*比较高效的C代码*/
- }
- void f__Fc(char c) {
- //*比较高效的C代码*/
- }
以这种方式重写这段代码将会很快,也很简单;但遗憾的是,这段代码仍然是不可移植的。为了既得到效率又具有可移植性,我们首先要改变C函数的名称(见练习9.5),使用如下命名: - /*C代码*/
- void f_int(int i){/*...*/}
- void f_char(char c)(/*...*/)
接下来,我们改写f的C++(www.cppentry.com)定义,如下所示: - extern "C" {
- void f_int(int i);
- void f_char(char c);
- }
- void f(int i){f_int(i);}
- void f(char c){f_char(c);}
从上面可以看到,和前面一样,编写可移植代码需要花费更多的精力。