以下未标注的都是C++特有的功能
1.内联函数
在普通的函数定义前加一个inline,如:
inline double square (double a) {return a*a}
它在调用的时候,和普通函数调用是一样的,只是说,它节省了一点处理调用的时间,但同时也消耗了内存,实际应用价值不大。
2.引用变量
格式:int & a = b;
这说明变量名a和变量名b完全是一回事。注意在声明引用的时候,就必须进行初始化,不可以先声明再初始化。
将引用用在函数调用中,即按引用传递,这能够让函数直接使用变量,如:
int main()
{
…
int k = Test(a)
…
}
int & Test(int &b)
{…
return b}
在上面的应用中,b和a共享同一个存储单元,只是名字不同而已,因此在函数内修改变量b,会对函数外的a也造成修改。在C语言中,要做到这一点就需要传递地址,即用指针变量。
而返回值也为引用,相当于b的值直接赋给k。而按值返回是,b赋值给一个临时位置,然后临时位置再赋给k,因此在大数据传输时,特别是结构体操作中,用按引用传递和按引用返回更佳。
在涉及到类对象时,常用引用
3.默认参数(不同的参数数目调用同一个函数)
通过函数原型设置默认值,这样可以让函数在缺失某些参数的时候,仍然可以运行。但是在设置默认参数时,注意,如果某一参数N设置了默认值,那么这一参数的右边所有参数都要设置默认值(这很好理解,因为如果不这样操作,那么势必会导致用户不知道自己的值赋给了哪个参数)。在调用的时候,赋值必须从左往右按顺序,不能跳过任何参数。
void PrintResult(int a=1)
{…}
4.函数重载(相同的函数名调用不同的函数)
这样做的前提是,相同函数名的函数们具有不同的特征标(注意不是函数返回类型),特征标包括参数类型和参数数量,只要其一不同就不同。特别注意:类型引用和类型本身属于同一特征标。
注意:const变量,只能传给形参为const的函数,而非const变量都可以,因为可以被强制转换为const变量。
5.函数模板(泛型编程)
这个就是数据结构中的用DataType定义数据类型,利用typedef即可完成任务。
在C++中可以用template来实现,并且这笔typedef更加方便,比如:
template <typename AnyType> //注意这里的 typename 关键字可以换为 class 关键字, AnyType是类型名而已,因此可以替换为任意名字,如T。
void Swap(AnyType &a, AnyType &b)
{
AnyType tmp = b;
b = a;
a = tmp;
}
如果在函数中定义了上述代码,那么在主函数中,使用两个int类型的参数输入到Swap中,那么程序会生成一个int类型的版本,使用两个double类型的参数输入到Swap中,那么程序会生成一个double类型的版本,即以下的调用完全合法:
int main()
{
...
double a,b;
int c,d;
char e, f;
Swap(a, b);
Swap(c, d);
Swap(e, f);
...
return 0;
}
6.重载的模板
两个函数名相同的模板,特征标不同,即可完成重载:
template <typename AnyType> //注意这里的 typename 关键字可以换为 class 关键字, AnyType是类型名而已,因此可以替换为任意名字,如T。
void Swap(AnyType &a, AnyType &b)
{
AnyType tmp = b;
b = a;
a = tmp;
}
template <typename AnyType> //注意这里的 typename 关键字可以换为 class 关键字, AnyType是类型名而已,因此可以替换为任意名字,如T。
void Swap(AnyType &a, AnyType &b, int n)
{
...
}
从以上结构可以看出,模板函数中的形参不一定要是全是模板参数类型AnyType,可以有int等其它基本类型。
模板仍然有一些局限性,比如对于一些输入的数据结构,里面的符号运算并不能对这样的数据结构进行操作(例如对两个指针做乘法),这样就需要用到显式具体化和实例化的操作
显式具体化:
template <> void Swap(double &a, double &b, int n)
{
...
}
像这样的,一旦前两个参数是double类型的,就会匹配以上函数,即显式具体化的优先级高于模板函数。