Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1685245
  • 博文数量: 311
  • 博客积分: 7778
  • 博客等级: 少将
  • 技术积分: 4186
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-09 19:59
个人简介

蓝点工坊(http://www.bluedrum.cn) 创始人,App和嵌入式产品开发。同时也做相应培训和外包工作。 详细介绍 http://pan.baidu.com/s/1y2g88

文章存档

2012年(3)

2011年(115)

2010年(170)

2009年(23)

分类: C/C++

2010-04-01 14:41:18

 
Andrew Huang
 
 
 C++在函数中扩展不少地方。主要在源码上。主要有如下几项
1.参数缺省值
2.内联函数
3.重载函数.
 
4.重载的实现原理和影响。
 
 
  但是为为了实现重载又在编译结果做了一些特殊处理。这样带了一些连锁反应,这样在一些底层程序编写时要对函数做一些特殊处理。
 
一.参数缺省值
 
  函数的参数缺省值就是指在调用函数时,有一些部分形参的值如果没有赋值,将会被赋给一个缺省值,象如下代码

void print(int a,int b=20,int c=30)
{
  printf("a=%d,b=%d,c=%d\n",a,b,c);
}

void test1()
{
  print(1,2,3);
//完整调用

  print(1,2) ;
//c将等于30;

  print(1);
//b将等于20,c将等于30

}

上述代码中print()中的b,c就是使用缺省值。
 
缺省值的作用,缺省值的主要作用用于扩展函数功能。在C中老的函数如果改变了参数定义,必须把所有引用这个函数的地方重改写编译一次。而且有了缺省值后。原有调用不变,而新增参数使用缺省值。这样就无需调整原有代码而可以使用新的功能了。
 
另外一个功能是把最高频使用的参数值做成缺省值,这样可以调用语句最简单。
 
参数缺省值有其优点,但是使用起来有很多限制.
 
限制1. 带缺省值参数要定义在不带缺省值参数后面
     int func1(int a=30 ; int b) ; 是错误定义
限制2.调用函数时, 如果定义在前面参数采用缺省值,但后面参数不使用缺省值, 将产生编译错误
     int func(int a = 10, int b=20);    
     func(,30); //这是错误用法。
限制3.参数缺省值的声明只能出现一次。 不能同时出现在外部声明和函数实现中,下例将产生编译错误
    extern int func(int a= 10 ; int b=20);
        int func(int a=10; int b=20)
        {
        
        }

二.内联函数

 内联函数是指在函数声明或实现时加上inline关键字。这种函数有一般函数绝大部分特性。比如有类型检查,可以单步调试,函数内部的书写也跑普通函数一样。比如下例

inline float converter(float dollars);
 
内联函数跟一般函数的最大区别是在编译时,内联函数将源码直接在调用的地方展开,因此也不存在函数调用时,参数和局域变量压栈和出栈的开销。频繁调用的小函数最适合定义成内联函数.
 
代码展开这一点象多语句宏。但是多语句宏的缺点也很多。一是没有类型检查.二是碰到++,--很容易出错,三是无法单步调试。  inline 就比较完美解决这三个问题.因此C++也大量使用内联函数。
 

inline void swap03(int &a ,int &b)
{
  int tmp = a;
  a = b;
  b = tmp;
}

但是注意几点。

 C++ 编译器有可能会忽略inline关键字,而且 不允许为不同的源文件中的内联函数指定不同的实现。

三.函数重载

C语言有重要一条,在同一个程序中,函数不能重名,因为最后会被链接不同地址上去。因此C语为了解决重名的问题,一般是采用在函数名前面或后面加入前缀或后缀来解决名字冲突。

如 list_init();

但是C++对于这一点没有这么严格,只要不同的参数列表,函数可以重名,这种叫函数重载(overload).这里不同的参数列表的条件非常简单,只如下三个条件只要满足一条即可以重载。

参数的个数,对应位置参数的类型,参数的排列顺序。

象如下就典型的重载函数

int max(int a,int b)
{
  return (a>b? a : b);
}

double max(double a,double b)
{
  return (a>b? a : b);
}

char max(char a,char b)
{
  return (a>b? a : b);
}

const char max(const char a,const char b)
{
  return (a>b? a : b);
}

 

注意两点,一个类型加上 const 后算另一个类型,比如C++中,const int 和int 算两个类型。如果参数完全相同,只有返回值不同,不能重载。

编译器通过调用时参数的个数和类型确定调用重载函数的哪个定义

4.重载的实现原理和影响

 C++是如何实现重载的?我们可以在Linux下用nm来导出符号表来看一下,其中C的函数名在符号表里没有变,但是C++的函数名会被编译器增加一些前缀和后缀

 如重载的max在符号表里实际上是这样的.换句话说,在链接时还是用不同的名字,        

    080484a8 T _Z3maxdd
    08048464 T _Z3maxii

C++编译器就是这个方法来实现重载,不同平台C++编译器加后缀的方法虽然不同,但实现思咱是一样的。

这个加后缀的方法带来什么影响?一个影响是当C++函数去调用C编译出来程序。会产生"错觉",也会加后缀来链接C函数。这样会产生链接错误。为了解决这个问题。在C++中可以用extern "C" 来声明是C函数,这样C++ 链接时,不会把C函数名加后缀

extern int c_func(int a,int b); //单个定义


extern "C" { //成片定义
    int c_func1(int a,int b);
    int c_func2(int a,int b);
}


这也是是为什么C的库函数的头文件为什么要加上这样一段。

#ifndef __STD_IO_H__
#define __STD_IO_H__

#ifdef __cplusplus
extern "C" {
#endif

 
// C函数定义

#ifdef __cplusplus
}
#endif


#endif /* __STD_IO_H__ */

___cplusplus是编译器内置宏。当编译器是C++才定义,在C编译器下相当什么都没加,而在C++链接时,而把所有extern "C" 包含的函数都定义成C函数。

 

练习题

 1.C++怎么引用汇编语言的"函数"?

   汇编采用label来实现类似函数功能,本质上跟 C函数一样,同样在C++中要用extern "C"声明;

 2.还有一种奇怪的应用,在C编译器下,怎么链接C++的库或目标文件?换句话说就是C怎么样调用C++程序!

  同样还是用extern "C" ,在C++程序,定义一个extern "C"的代理函数。在C程序中通过代理函数来间接调用C++函数

 

 

 

 

 

 


 



阅读(1457) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~