c++ primer(第五版)笔记 第六章 函数(2)

来源:互联网 发布:数据库的基本结构 编辑:程序博客网 时间:2024/06/16 04:43
#ifndef FUNC_H#define FUNC_H#include<iostream>#include<string>#include<vector>#include<cstdlib>using std::cout;using std::cin;using std::endl;using std::string;using std::vector;char &get_val(string &s, string::size_type pos);//可以将小型函数定义为内联函数(inline function),可以减少函数调用的开销// inline 只是向编译器请求,编译器可以选择忽略。。。//如果要将 inline 的声明和定义分开文件,需要注意/*csdn 论坛:http://bbs.csdn.net/topics/100081253我概括过inline函数的一条基本原则(不知道别人有没有类似提法):首先介绍一个概念,“编译单元”,用不太严谨的方式定义,就是当你把一个源文件(.cpp .cxx等)做完预处理,也就是把包含的头文件的内容全部放到这个文件里来,所有宏都展开,等等,形成的一个逻辑上的实体——就是编译单元一个编译单元可以单独编译,但不能链接成一个可执行程序(除非程序只有这个编译单元)有了编译单元的概念以后,你只要确保以下这个原则就可以了:如果在这个编译单元里使用了一个Inline函数,那么我在这个编译单元结束之前,必须能够“看到”这个编译单元的完整定义(所有实现代码)另外要注意,在编译单元之内,调用inline函数的代码行之前,至少要放置一个这个inline函数的声明,当然有定义也可以从这个原则出发,最简单的使用Inline函数的方法就是在头文件定义,否则你要在每一个使用inline函数的编译单元里一一定义这个函数,如果有n个编译单元,你就要把inline函数的代码重复书写n次*///返回列表inline vector<int> get_vector(){return{3,4,52};}//定义返回数组指针的函数//1.定义类型别名typedef int parr[5]; //using parr = int[5];extern int arr1[5];extern int arr2[5];parr *func1(int);//2. 不使用类型别名//Type ( *function( parameter_list)) [ demension]//Type 数组元素的类型, demension 数组的维度, function 函数名int ( *func2( int))[ 5];//func1 不使用类型别名//3.使用尾置返回类型(trailing return type)auto func3(int i) -> int(*)[5];//4.使用已知数组和 decltype 关键字decltype(arr1) *func4(int i);decltype(arr1) &func5(int i);//重载函数(overloaded):同一个作用域内函数名相同,形参列表(形参数量和类型)不同//main函数不能重载//不允许两个函数除返回类型以外的其他要素都相同//顶层 const 形参和无顶层 const 的形参没有区别,拷贝初始化时忽略顶层 const//底层 const 指针或引用,通过区分指向对象是常量还是非常量来实现函数重载//const_cast 强制类型转换const string &shorter(const string &s1, const string &s2);//如果需要返回非常量string &shorter(string &s1, string &s2);//默认实参(default argument),当为一个形参赋予了默认值,则其后面的所有形参都必须有默认值// 调用时,如果想覆盖某位置的默认实参,则必须为该位置之前的所有形参赋予实参//一般在头文件中提供默认实参,并且在同一个作用域内,一个形参只能被赋值一次//函数匹配(function matching)//重载确定(overload resolution)// 1.选定本次调用的重载函数集,候选函数(candidate function)// 规则:1>同名 2.声明在调用点可用// 2.考察实参,可行函数(viable function),如果找不到报告无匹配函数的错误// 规则:1>形参数量和实参数量一致 2>实参的类型和对应形参的类型一致// 3.最佳匹配// 1>精确匹配// 形参和实参类型相同// 实参从数组类型或函数类型转换成对应的指针类型// 顶层 cosnt // 2.底层 const 转换// 3.类型提升// 4.算术类型转换// 5.类类型转换//三种调用结果://1>编译器找到一个与实参最佳匹配(best match)的函数,生产调用该函数的代码//2>找不到与实参匹配(no match)的函数,编译器报无匹配的错误//3>有多于一个函数可以匹配,但都不是最佳匹配,报二义性调用(ambiguous call)错误//函数指针//由返回类型和形参列表共同决定//不同类型的函数指针不存在转换规则,但可以用 nullptr 或 0 的整型常量表达式赋值//func1 的指针, 可以直接使用 pfunc1 调用函数extern parr *(*pfunc1)(int);//重载函数的指针,指针类型必须与重载函数的其中一个精确匹配string &(*pShorter)(string &s1, string &s2);//未定义#endif//FUNC_H

#include "func.h"char &get_val(string &s, string::size_type pos){//retrun 终止当前正在执行的函数并将控制权返回该函数调用的地方//两种形式: //return;//只用于返回类型是 void 的函数中,也可以使用 returned expression 形式,但 expression 必须是一个返回 void 的函数//returned expression//只要函数的返回类型不是一个 void,则函数内的每条 return 语句必须返回一个值,该值的类型必须和函数的返回类型一致,或者能隐式转换//函数完成后,所占用的存储空间也随之被释放掉,函数终止意味着局部变量的引用和指针不再指向有效的内存区域return s[pos];//pos 合法}int arr1[5]{1, 2, 3, 4, 5};int arr2[5]{6, 7, 8, 9, 0};//1.类型别名parr *func1(int i){return (i % 2) ? &arr1 : &arr2;}//2.不使用类型别名int(*func2(int i))[5]{return (i % 2) ? &arr1 : &arr2;}//3.使用尾置返回类型 c++11auto func3(int i) -> int(*)[5]{return (i % 2) ? &arr1 : &arr2;}//4.使用已知数组和 decltype 关键字decltype(arr1) *func4(int i){return (i % 2) ? &arr1 : &arr2;}//将 func4 改成返回引用decltype(arr1) &func5(int i){return (i % 2) ? arr1 : arr2;}//const_cast 强制类型转换const string &shorter(const string &s1, const string &s2){return s1.size() <= s2.size() ? s1 : s2;}//如果需要返回非常量的重载函数string &shorter(string &s1, string &s2){auto &r = shorter(const_cast<const string&>(s1), const_cast<const string&>(s2));return const_cast<string&>(r);}//constexpr 函数,能用于常量表达式0//所有的形参类型和返回类型均为字面值类型,函数体中有且只有一条 return 语句//隐式定义为 inline //允许返回值是一个非常量constexpr int cexpr1(){ return 21;}constexpr int cexpr2(const int n){ return cexpr1() * n;}extern int arr3[cexpr2(2)]; int m = 1;// extern int arr4[cexpr2(m)];//cexpr2 返回非常量parr *(*pfunc1)(int) = func1;//取地址符可选 parr *(*pfunc1)(int) = &func1

#include "func.h"int main()//main函数不能重载{string s{"hello world"};vector<int> vi;get_val(s, 3) = 'M';//调用返回引用的函数得到左值cout <<"s : "<< s << endl;vi = get_vector();for (auto i : vi)cout << i << endl;parr *p1 = func1(2);int (*p2)[5] = func2(3);int (*p3)[5] = func3(5);int (*p4)[5] = func4(2);int (*p5)[5] = pfunc1(2);//直接使用 pfunc1 调用函数,解引用符可选(*pfunc1)(2)for (size_t i = 0; i != 5; ++i){cout << "P1: " << (*p1)[i] << endl;cout << "P2: " << (*p2)[i] << endl;cout << "P3: " << (*p3)[i] << endl;cout << "P4: " << (*p4)[i] << endl;cout << "P5: " << (*p5)[i] << endl;}func5(2)[3] = 6234;//返回引用类型可作为左值for (size_t i = 0; i != 5; ++i){cout << "arr2: " << arr2[i] << endl;}// const_cast 和 重载string s1 = "hello";string s2 = "world!";// shorter("hello", "world!")[2] = 'H';//调用const 形参版本,返回指向 const 对象的引用,不可以修改shorter(s1, s2)[2] = 'H';//调用非const 形参版本,返回非 const 引用,如果未定义非 const 形参版本,则返回 const 引用cout << s1 << endl;//允许 main 函数没有 return,编译器隐式插入一条返回 return 0 的语句//0 表示执行成功,非 0 值具体含义由机器定义。cstdlib 定义了两个预处理变量 EXIT_FAILURE, EXIT_SUCCESSreturn EXIT_SUCCESS;}

0 0
原创粉丝点击