现在的位置: 首页 > 综合 > 正文

c++对c的升级

2019年04月20日 ⁄ 综合 ⁄ 共 3658字 ⁄ 字号 评论关闭

C++中增加 bool类型占一个字节,可取值有true在内部用1表示 false0表示(这两个是关键字不是宏定义的),即使给bool类型赋非零值,这个变量也是1; 

C++中对三目运算符的升级:在c中三目运算符返回的是值,而在c++中三目运算符返回的是变量的引用(若有常量则返回的是值,不可作左值)

 

C++中的引用:对于一段连续的空间可以起多个名字 

引用类型 &引用变量名 变量名;

注意:1. 引用的地址与其对应的变量的地址一样;

     2. 普通引用在定义的时候必须用变量初始化不能用常量初始化,做函数参数时不初始化,在定义含引用类型的结构体类型时时,引用作成员变量时不初始化;

      3. 引用的地址就是变量的地址

Const引用: const  引用类型 &引用变量名 变量名;

让引用变成只读的不能通过引用改变变量的值了(即不能做左值),但还是可以通过原变量来修改,或者通过变量的地址来改变

    int a = 4;

    const int &b = a;

    int *p = (int *)&b;

    

    // b = 4;  这里不能通过引用来改变 

    a = 5;  //  通过原变量来修改

    cout << a << endl;

    *p = 6;// 通过变量的地址来改变

    cout << *p <<endl; 

 

Const引用可以用常量来初始化,这时会为常量分配空间改变为只读变量并将引用作为只读变量的别名,但不能通过引用修改这个地址的内容,可以通过地址来改变里面内容(指针方式)

    

    const int& b = 1;

    int* p = (int*)&b;

 

    //b = 5; //不能通过常引用修改只读变量的内容

    *p = 5; //但可以通过地址修改只读变量的内容

 

 

引用有自己的存储空间在32位上是4个字节,其在c++内部实现是一个常指针,即 

引用类型 &引用变量名 <——类型 * const 变量名

struct TRef

{

    int& a;

    int& b;

};

 

int main(int argc, char *argv[])

{

    printf("sizeof(TRef) = %d\n", sizeof(TRef)); //打印结果为8

 

引用做函数返回值:1. 返回栈变量(局部变量),不能为其他引用的初始值、不能作为左值使用

2. 返回静态局部变量或全局变量,可以成为其他引用的初始值、也可作左值使用

int& f()

{

    static int a = 0;

    

    return a;

}

 

int& g()

{

    int a = 0;

    

    return a;

}

 

int main()

{

    int a = g(); //将局部变量通过引用的方式的值给a

    int& b = g(); //用局部变量的引用初识化引用,由于局部变量已经被回收,所以里面的内容不可预测

    

    f() = 10;

    

    printf("a = %d\n", a); //0

    printf("b = %d\n", b);  //不可预测

    printf("f() = %d\n", f()); //0

 

函数的升级:内联函数来替代中的宏代码片段,直接将函数体插入函数调用的地方,减少了压栈跳转返回的开销 

方法:inline必须和函数定义结合在一起

 

内联函数与宏代码片段的区别;内联函数在本质上还是函数,所以会进行参数返回值类型的检查,而宏只是进行简单的替换

 

内联函数的深度分析

在安装软件的相应目录下找到g++.exe将其路径添加到环境变量,就可在DOS下使用g++命令

内联中不能有循环和判断不能大不能对函数名取地址,否则编程普通函数

内联函数的实现机制

将内联函数存入符号表,在用时从符号表中取出函数体替换函数

 

函数默认参数:在函数声明时可以为函数参数指定默认值,在调用函数时没有提供实参时以默认值为实参

函数占位参数:在函数定义时可以提供没有名字只有类型的参数做占位,调用时必须提供实参,但在函数体中无法使用占位参数  

int fun(int a, int b, int)

{}

意义:

1. 占位参数与默认参数结合使用,为以后扩展留下线索

int fun(int a, int b, int = 0)

{}

2. 占位参数与默认参数结合使用,兼容c中可能出现的不规范的写法

 

 

 

 

重载:同一标示符在不同上下文有不同的意义

C++ 支持函数重载:用同一函数名定义不同函数,但须至少满足以下一个条件

1. 函数的参数类型不同

2. 函数的参数个数不同

3. 函数的参数顺序不同

注意:与函数返回值没任何关系

int func (int x, const char *s)

int func (int x, int y)

int func (const char * s, int x)

int func (int x)

几个函数是重载函数,有各自的意义,并且是相互独立的

 

 

 

函数默认参数遇上函数重载

Int func (int a, int b, int c = 0);

Int func (int a, int b);

是重载

Func(1, 2); //这里既可以认为是调用Int func (int a, int b);也可以认为是调用Int func (int a, int b, int c = 0);

只不过使用了函数的默认参数,因此不用写第三个参数。由于出现了二义性,编译器是不能编译通过的。

结论:在开发中不能同时使用函数重载和默认参数

 

编译器调用重载函数的准则

Int func (int a, int b, int c = 0);

Int func (int a, int b);

 

Func(1, 2);

Func(“a”, 2);

Func(1);

1. 将所有同名函数作为候选者  //将两个func函数作为候选者 

   2. 然后按如下规则寻找

精确匹配实参 //Func(1, 2);可以匹配第二个函数 

通过默认参数能够匹配实参 //Func(1, 2);可以匹配第一个函数

通过默认类型转换匹配实参 //Func(“a”, 2);可以匹配第二个函数

3. 匹配失败原因

找到的函数不唯一出现二义性,编译失败 //Func(1, 2);可以匹配两个函数,编译失败

无法匹配所有候选者,函数未定义,编译失败 //func(1);无法匹配,编译失败

 

函数重载遇上函数指针

当使用重载函数名对函数指针赋值时,首先会根据重载规则调选与函数指针参数列表一致的候选者,然后严格匹配候选者的函数返回类型与函数指针的函数返回类型一致

C++和C的相互调用

c++的编译方式跟c编译方式不同

C++中调用c程序

C++编译器能够兼容c语言的编译方式,但c++编译器会优先使用c++的方式进行编译。可以使用extern关键字强制让c++编译器对程序使用c方式编译

 

extern  C

{

需要以c方式编译的代码段...

 

C中调用c++程序:将c++c的方式编译,供c程序调用

 

技巧:__cplusplusc++编译器内置的标准宏定义,可以利用它来定义让c代码即可以在c编译器中编译也可以在c++编译器中以c方式编译

 

#ifdef __cplusplus

Extern “C” {

#endif

//函数声明或定义段

#ifdef __cplusplus

}

#endif

 

C++编译器不能以c的方式编译多个重载函数

 

扩展:被extern "C"修饰的变量和函数是按照C语言方式编译和连接的;

未加extern“C”声明时的编译方式

首先看看C++中对类似C函数是怎样编译的。

作为一种面向对象的语言,C++支持函数重载,而过程式语言C则不支持。函数C++编译后在符号库中的名字与C语言的不同。例如,假设某个函数的原型为:

voidfoo( int x, int y );

函数C编译器编译后在符号库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字(不同的编译器可能生成的名字不同,但是都采用了相同的机制,生成的新名字称为“mangled name”)。_foo_int_int这样的名字包含了函数名、函数参数数量及类型信息,C++就是靠这种机制来实现函数重载的。例如,在C++中,函数void foo( int x, int y )void foo( int x, float y )编译生成的符号是不相同的,后者为_foo_int_float

同样地,C++中的变量除支持局部变量外,还支持类成员变量全局变量。用户所编写程序的类成员变量可能与全局变量同名,我们以"."来区分。而本质上,编译器在进行编译时,与函数的处理相似,也为类中的变量取了一个独一无二的名字,这个名字与用户程序中同名的全局变量名字不同。

 

 

 

 

 

 

抱歉!评论已关闭.