您的位置:首页 > 编程语言 > C语言/C++

20161221C++阶段班02_C to C++_02重载/默认实参/inline/类型转换

2017-01-11 17:17 197 查看

Overloaded:

  重载导致的二义性:

1:为什么要重载,为了方便对函数的调用!同一功能的函数不用起不同名字。当写函数的时候可能开始不知道要传递那些参数,我们可以用重载多写几个类型的函数来解决。重载不影响运行效率,只影响编译效率。

2:匹配:当调用函数的时候传递的参数类型在重载函数里面都没有,编译器就会自动进行类型匹配。如果有对应的类型,编译器肯定会调用对应的类型。编一起的自动类型匹配是有一定规则的,自动匹配如果可以匹配的重载函数超过一个,他就可能不知道调用哪一个重载的函数了(这不符合匹配的规则),

    1:精准匹配:准确的,int到int,char到char……(有精准匹配的时候编译器就不会匹配到其他函数,也不会报错)
    2:提升匹配:char->int,float->double,short->int,long->int(所有的字面值整数都为int类型?所有的字面值浮点数都为double)。
    3:类型转换匹配:int->unsigned int(反之不行)
3:二义性:

当有多个匹配时,匹配的规则出现冲突的时候,就会出现二义性,那么就需要让他不冲突,修改成精准匹配可以解决问题!
在需要重载时,定义了太多或者太少重载函数都是不太好的!最好全用精准匹配,但写得多也可能出问题,重载的时候,最好根据业务需求来定,不能写的太多,也不能写的太少。
重载的时候,最好不要用int *等指针,容易出错。

#include <cstdio>
void MyCout(int i)
{
printf("%d\n", i);
}
void MyCout(char c)
{
printf("%c\n", c);
}
void MyCout(float f)
{
printf("%f\n", f);
}
void MyCout(char *c)
{
printf("%s\n", c);
}
int main()
{
long lNum = 100;
MyCout(lNum);
return 0;
}//这个调用就会自动匹配到int那一个函数。


头文件的三种标准:

    #include <iostream>,这个库不以.h结尾,后缀名适用于区分使用,不加.h里面的内容也是一样的。
    C++是从C语言发展而来的,里面有几个标准:1:.h结尾的,就是从C继承来的。2:前面前缀c(eg:#include <cstdio>),也是从C继承过来的,但是这个符合C++标准,他和stdio.h里面基本一样,只是cstdio符合C++标准。使用C语言的标准库应该使用cstdio。3:标准C++库(#include <iostream>)。

Default Argume默认实参:

一些函数里面的参数需要有默认值,就可以使用默认参数。例如:

#include <cstdio>
void MyCout(int i, bool line = true)
{
printf("%d", i);
if (line) printf("\n");
}
void MyCout(char c, bool line = true)
{
printf("%c", c);
if (line) printf("\n");
}
void MyCout(float f, bool line = true)
{
printf("%f", f);
if (line) printf("\n");
}
void MyCout(char *c, bool line = true)
{
printf("%s\n", c);
if (line) printf("\n");
}
int main()
{
long lNum = 100;
MyCout(lNum);
MyCout(lNum, false);
MyCout(lNum, true);
MyCout("i love C++", false);
MyCout("i love C++");
return 0;
}




    如果里面每个参数都设置成有默认实参的,调用的时候就可以一个参数也不传,但如果重载了多个全都有默认实参的函数,调用的时候不传参数就会出错(不知道调用哪一个),二义性。默认实参规定出现在函数参数的最右边,或者参数排列从右到左,不能第一个参数有默认值,后面的参数没有默认值。

    解决二义性的方法1:使之唯一匹配。2:调用的时候确定他的精确参数(强制转换等方法)。

内联函数:

    在函数之前加上inline:代表我们想把这个函数做成一个内联函数,调用的时候会将这个函数展开,这样好处在于内联函数不会新建栈,他只是将函数展开,最大的好处在于运行的效率会大大的提升,坏处在于生成的exe文件体积会膨胀,代码膨胀不止来源于内联函数(在模版里面膨胀会非常大)。不会影响内存。有值返回的内联他会自动进行值的替换。但是所有写了inline的函数并不是100%会成为内联函数,会根据编译器的判断来完成,编译器认为可以展开的话才会成为内联函数(由编译器来决定,有一定的判断标准),不加inline的话肯定不会成为内联函数。
    inline函数判定标准,不同的编译器会有所不同,一般都会更具栈的使用情况来判定,inline主要提高函数调用的时间(call),分配栈的这些可以放在一个函数里面一次性分配(不然每次调用都会再次分配)。如果inline函数里面使用了大量的栈,就可能不会将这个变为一个内联函数,被判定为inline的函数一般不会使用大量的栈,调用简单(调用函数少,无递归等),不一定行数少的就可以被判定为inline,与函数关系不大,但一般都规定inline函数有一定的行数限制,超过就不要写成inline(规律)。
    宏是100%展开,inline与之的区别是inline他会进行类型的检测,使用inline,他还是一个函数,宏他只是纯粹的替换。inline函数过多,会导致编译器的判断花很长时间,编译过程耗时很长。

代码膨胀:

编译的时候首先会进行预处理过程,他会生成很多代码(展开#include,计算sizeof等……),然后会展开inline,然后会展开泛型。代码膨胀可以提高编写程序的效率,生产力会较高(java每行都可能膨胀成上十行),但代码膨胀会导致调试程序的困难,因为他是编译器生成的,出错了很难找到错误出现的地方。难以找到bug的位置。

类型转换:

C++里面新出的,C语言中,类型转换用(int)……这种方式,告诉编译器这是我知道的,就要转换。隐式转换是非常危险的(除法的时候会讲int转化为double)。C++里面有四种类型转换符,他的自由度是比C语言高些的。
    1:static_cast<>……eg:int num = static_cast<int>1.0003;//这并不是强制转换,他只是表示转换,结果是一样的,经常用于把基类指针指向派生类指针的转换。这是标准的C++风格。

    2:const_cast<>……在特定情况下使用,他可以使const变成非const,可以移除对象的常量性,但是还是不能修改内容。用于使参数进行参数的匹配。使得语法上不会有问题!一般用于指针,引用……

    3:reinterpret_cast<>……强制转换,二进制层面的转换,相当于拿着指针来拷贝(一般用于指针的转换),是比较危险的转换,最好不要用!

    4:dynamic_cast<>……类型推导转换符
4000
!在写非常大的框架的时候会用到。

这四种类型转换与C语言的属于不同的风格,C语言的转换属于暴力的方式转换,有安全和不安全,不管怎么样都会转换成功。C++中将这种转换拆分成了static_cast<>和reinterpret_cast<>,前者相对会安全一些,后者100%有问题,不安全,是开放的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: