C++是一个面向对象语言(虽不是纯粹的面向对象语言),它支持函数的重载,重载这个特性给我们带来了很大的便利。为了支持函数重载的这个特性,C++编译器实际上将下面这些重载函数:
void print(int i); void print(char c); void print(float f); void print(char* s); 编译为:
_print_int _print_char _print_float _pirnt_string 这样的函数名,来唯一标识每个函数。注:不同的编译器实现可能不一样,但是都是利用这种机制。所以当连接是调用print(3)时,它会去查找_print_int(3)这样的函数。下
C语言中并没有重载和类这些特性,故并不像C++那样print(int i),会被编译为_print_int,而是直接编译为_print等。因此如果直接在C++中调用C的函数会失败,因为连接是调用C中的print(3)时,它会去找_print_int(3)。因此extern "C"的作用就体现出来。
(二)static关键字 1.static和extern不能同时修饰一个变量; 2.static修饰的全局变量声明与定义同时进行,比如static int val,此时变量val所占的内存已经被分配了. 3.static变量只在该文件内有效,如果.h文件中有定义static double price,那么每个include此h文件的模块都有一个单独的price变量,互不干扰. 4.static函数,如果static函数是类的成员,则此函数只能操作static成员. 5.c++中,类的static成员,不必实例化即可调用,比如Ctype::FuncName(),类的static数据成员,只占一份内存. 6.如果有如下的函数声明: static char func(void); 其中的static关键字不是修饰返回值char的, 而根据语境, 1修饰函数只在文件内有效, 2如果函数是类成员, 则表明这个函数可以在类没有实例化前而调用AClass::func(); 在C/C++中, static变量都是存储在常量区, 生存周期都是一旦被创建, 一直存在. 在C语言中, static有了第二种含义:用来表示不能被其它文件访问的全局变量和函数. 在C+ +中, static还有第三种含义:表示属于一个类而不是属于此类的任何特定对象的变量和函数. 对于类的static成员, 该类的所有实例都共用一个static成员.比如在对某一个类的对象进行计数时, 计数生成多少个类的实例, 就可以用到静态数据成员. 注意, static成员函数必须只能调用static成员. (三)const关键字 在C语言中, 常用#define MAX 1024这样的宏定义, 但是C++中不推荐这样做, 而采用const变量的方式定义一个常量. 1. 修饰常量/指针: const int *p = &val; //p指向的类型是const int,指向的内容不能改变; int const *p = &val; //同上 int * const p = &vala; //p指向的类型是int,指针本身的值不能改变; const int * const p = &a; 2.const对象应该在定义时被赋值, const int* a = new int(0)[1024]; //ok 3.多文件中使用const变量: extern const char g_str[]; //h文件声明 const char g_str[] = "123"; //c文件定义 4.函数中指针的const传递和返回: const char* F2(); //意义是函数返回的指针指向的对象是一个const对象,它必须赋给一个同样是指向const对象的指针。 const char* const F3(); //比上面多了一个const,这个const的意义只是在他被用作左值时有效,它表明了这个指针除了指向const对象外,它本身也不能被修改,所以就不能当作左值来处理。 const char F2(); // 不修饰指针/引用的情况, 无意义, char c = F2() 不报错. 5.int Func() const; //函数Func()是类成员,表示此函数不能改变类对象,反之则编译器报错; 6.const在函数重载中的问题: 《C++ primer》中提到“仅当形参是引用或指针的时候,形参是否为const才对重载有影响。” const重载情形(1): int add(int a, int b); int add(const int a, const int b); // 无意义的重载 在此的两个函数的形参并不会直接关联到实参,在调用这两个函数的时候,形参都只是实参的一个副本,不管add函数内部对 形参做什么处理,都不会影响到实参,也就是说——第二个函数形参中的const没有任何的用处,只是多此一举罢了。所以在此的第二个定义只是对第一个的重 定义罢了。 实参为非const对象的时候,其实两个版本函数都可以被调用,都与之匹配,因为非const对象不但可以初始化非const引用,也可以初 始化const引用。但由于非const对象初始化const引用的时候涉及到类型转换,所以此时带非const引用形参的函数为最佳匹配。 const重载情形(2): int add(int &a, int &b); int add(const int &a, const int &b);//可以重载 比如定义const常量x,y,代码中调用add(x,y)是第二个版本. 上述第2种情况:实参为const对象的时候,就不能将此对象传递给带非const引用的形参的函数了,因为const对象只能用来初始化const引用。 /*函数定义*/ int add(int *a, int *b); int add(const int *a, const int *b); int x = 1; int y = 2; const int r = 1; const int s = 2; add(&x, &y); //调用 add(int *, int *); add(&r, &s); //调用 add(cosnt int *, cosnt int *);