第八章 函数探幽
C++内联函数
要使用这种特性,必须采取下述措施之一:
在函数声明钱加上关键字inline;
在函数定义钱加上关键字inline。
内联函数和常规函数一样,也是值传递参数。
引用变量
引用是已定义的变量的别名。通过将引用变量用作参数,函数将使用原始数据,而不是其副本。
C++给&符号赋予了弄一个含义,将其用来声明引用。
必须在声明引用变量时进行初始化。引用更接近const指针,必须在创建时进行初始化,一旦与某个变量关联起来,就一直效忠于他。也就是说:
int & rodents =rats;实际上是下述代码的伪装表示:
int *const pr =&rats;
其中,引用rodents扮演的角色与表达式*pr相同。
将引用用作函数参数
这种传递参数的方法称为按引用传递。按引用传递允许被调用的函数能够访问调用函数中的变量。
引用的属性和特别之处
如果程序员的意图是让函数使用传递给他的信息,而不对这些信息进行修改,同时又想用引用,则应使用常量引用 应该在函数头和函数原型中使用const 例如 const double &ra 如果这样做,当编译器发现代码修改了ra的值时,将生成错误信息。
对于形参&x 在实参处不可以使用表达式会出现警告这时会使用一个临时变量等于表达式的值进行传递 实参应该是变量 而如果是形参是x 则可以。
如果实参与引用参数不匹配,C++将生成临时变量。当前,仅当参数为const引用是,C++才允许这样做。
什么时候创建临时变量呢? 如果引用参数是const 则编译器将在下面两种情况下生成临时变量:
1. 实参的类型正确,但不是左值;
2. 实参的类型不正确,但可以转换为正确的类型。
左值是什么呢?左值参数是可被引用的数据对象,例如,变量、数组元素、结构成员、引用和解除引用的指针都是左值。非左值包括字面常量(用括号括起的字符串除外,它们由其地址表示)和包含多项的表达式。
double refcube(const double *ra)
double side=7.0;
long edge =5L;
例如 refcube(7.0)// refcube(side+10.0)//refcube(edge)
在这种情况下,编译器都将生成一个临时匿名变量,并让ra指向它。这些临时变量只在函数调用期间存在,此后编译器便可以随意将其删除。
实际上对于形参为const引用的C++函数,如果实参不匹配,则其行为类似于按值传递,为确保原始数据不被修改,将使用临时变量来储存值。
应尽可能使用const
1.使用const可以避免无意中修改数据的编程错误;
2.使用const使函数能够正确生成并使用临时变量;
3.使用const引用使函数能够正确生成并确定临时变量。
右值引用 使用&&。
将引用用于结构
返回引用最重要的一点是,应避免返回函数终止时不再存在的内存单元引用。
对象、继承和引用
C++对象及类可见http://www.runoob.com/cplusplus/cpp-classes-objects.html
C++继承详情可见http://www.runoob.com/cplusplus/cpp-inheritance.html
默认参数
对于带参数列表的函数,必须从右向左添加默认值。也就是说,要为某个参数设置默认值,则必须为它右边的所有参数提供默认值:
int chico(int n;int m=12;int t); //错误
实参按从左到右的顺序依次赋给相应的形参,而不能跳过任何参数。因此,下面的调用是不允许的:
beep= chico(3, ,2); // 错误
函数重载
函数多态是C++在C语言的基础上新增的功能。默认参数让您能够适用不同数目的参数调用同一个函数,而函数多态(函数重载)让您能够使用多个同名的函数。
函数重载的关键是函数的参数列表——也称为函数特征标。
编译器在检查函数特征标时,将把类型引用和类型本身视为一个特征标。
函数重载不应乱用,仅当函数基本上执行相同的任务,但使用不同形象的数据时,才应采用函数重载。
名称修饰...
函数模板
函数模板是通用的函数描述,也就是说,他们使用泛型来定义函数,其中的泛型可用具体的类型替换。由于模板允许以泛型的方式编写程序,因此有时也被称为通用变成。由于类型是用餐食表示的,因此模板特性有事也被称为参数化类型。
template<typename AnyType>
void Swap(AnyType &a,AnyType &b)
要建立模板 template 是必须的 而 在C++98添加关键字typename之前 可用class创建模板
重载的模板
并非所有模板参数都必须是模板参数类型,和常规重载一样,被重载的模板函数特征标必须不同。
显式具体化
template <> void Swap <job> (job&,job&);
<job>是可选的,因为函数参数类型表明,这是job的一个具体化。
如果有多个原型,在编译器选择原型时,非模板版本优先于显式具体化和模板版本,而显式具体化优先于使用模板生成的版本。
实例化和具体化
为进一步了解模板,必须理解属于实例化和具体化。记住,在代码中包含函数模板本身并不会生成函数定义,他只是一个用于生成函数定义的方案。编译器使用模板为特定类型生成函数定义时,得到的是模板实例。模板并非函数定义,但使用int的模板实例是函数定义。这种实例化方式被称为隐式实例化,因为编译器之所以知道需要进行定义,是由于程序调用函数是提供了参数。
显示实例化
template void Swap<int>(int ,int );
实现了这种特性的编译器看到上述声明后,将使用Swap()模板生成一个使用int类型的实例。也就是说,该声明的意思是“使用Swap()模板生成int类型的函数定义。”
与显式实例化不同的是,显式具体化使用下面两个等价的声明之一:
template <> void Swap <int> (int&,int&);
template <> void Swap (int&,int&);
区别在于,这些声明的意思是“不要使用Swap()模板来生成函数定义,而应使用专门为int类型显式地定义的函数定义”。这些原型必须有自己的函数定义。显式具体化声明在关键字template后包含<>,而显式实例化没有。
https://blog.csdn.net/sunxiwang/article/details/78667444
http://blog.sina.com.cn/s/blog_612ec26f0102w2wg.html
试图在同一个文件(或转换单元)中使用同一种类型的显式实例和显式具体化将出错。
https://bbs.csdn.net/topics/390559301
https://bbs.csdn.net/topics/380250382
重载解析
https://blog.csdn.net/y1196645376/article/details/52860006
(完)