6.1 函数继承
1.局部静态对象
size_t count()
{
static size_t ctr=0;
return ++ctr;
}
int main()
{
for(size_t i=0;i<10;++i)
cout<<count()<<endl
return 0;
}//输出1到10的数字
局部静态对象第一次经过初始化,如果没有被显示初始化,则将执行值初始化(内置类型初始化为0),直到程序终止才被销毁。
6.2 参数传递
1.传值参数
指针形参可以改变所指对象的值,但在C++中建议使用引用类型的形参替换指针。
2.引用参数
- 使用引用避免拷贝
- 使用引用形参返回额外的信息
可以处理需要返回多个值得情况
3.const形参和实参
- 实参初始化形参是会忽略到顶层const
void fun(const int i){}//可以传递const和非const类型,但不能改变i值。
void fun(int i);//错误:重复定义
- 可以用非const初始化const对象,但反过来不行
int i=12;
const int *cp=&i;//正确,但cp不能改变i
const int &r=i;//正确,但r不能改变i
const int &r2=22;
int *p=cp;//错误:类型不匹配
int &r3=r;//错误:...
int &r3=22;//错误:...
- 尽量使用常量引用
4.数组形参
- 不允许拷贝数组,使用数组时自动转换成指针
- 使用beg和end传递数组参数
- 数组引用参数
void print(int (&arr)[10])
{
for(auto ele:arr)
cout<<ele<<endl;
}
int i=0,j[2]={1,2};
int k[10]={...};
print(&i);//错误:实参不是含有10个整数的数组
print(j);//error
print(k);//正确
- 传递多维数组
void print(int (*matrix)[10],int size);//等价于
void print(int matrix[][10],int size);
5.main:处理命令行选项
6.含有可变形参的函数
- initializer_list形参
是一个模板类型,但对象中的元素永远是常亮值
void error_msg(ErrCode e,initializer_list<string> il)
{
cout<<e.msg()<<":";
for(const auto &elem:il)
cout<<elem<<" ";
cout<<endl;
}
error_msg(ErrCode(42),{"functionx",expected,actual});
error_msg(ErrCode(42),{"functionx","okay"});
6.3 返回类型与return
1.返回值:不要返回局部对象的引用或指针
2.返回数组的指针或引用
- 使用类型别名返回数组指针
typedef int arrT[10];
using arrT=int[10];
arrT* func(int i);//返回一个指向含有10个整数的数组的指针
- 直接声明
int arr[10];
int *ap1[10];//含有10个指针的数组
int (*ap2)[10]=&arr;//指向10个整数的数组
//返回数组指针的函数形式如下:
Type (*function(parameter_list))[dimension];
int (*func(int i))[10];
3.使用尾置类型返回
- 使用尾置
auto func(int i)->int(*)[10];
- 使用decltype
int odd[]={1,2,3,4,5};
decltype(odd) *arrPtr(int i)
{
return ...
}
6.4 函数重载
- 重载和const形参
拥有顶层const的形参和没有const的形参无法区别
void func(int);
void func(const int);//error
如果形参是引用或者指针,则可以用const实现重载
void func(int*);
void func(const int*);//OK
2.const_cast和重载
const string &shorterString(const string &s1,const string &s2)
{
return s1.size()<=s2.size()?s1:s2;
}
string &shorterString(string &s1,string &s2)
{
auto &r=shorterString(const_cast<const string&>(s1),const_cast<const string&>(s2));
return const_cast<string&>(r);
}
6.5 特殊用途语言特性
- 默认参数
一旦有某个形参被赋予了默认值,后面的必须有默认值
调用时按先后顺序 - 内联函数和constexpr函数
内联机制用于规模小、流程直接、频繁调用的函数
constexpr用于常量表达式的函数
constexpr int new_sz(){return 42;}
constexpr int foo()=new_sz();
把内联函数和constexpr放在头文件中
3.assert预处理宏
assert(expr);//如果expr为真,则不做处理,如果为假,则输出信息并终止程序执行
4.NDEBUG预处理变量
可以使用NDEBUG编写自己的条件调试代码,如果NDEBUG未定义,将执行#ifndef和#endif之间的代码;如果定义了DNEBUG,这些代码将被忽略
void print(const int ia[],size_t size)
{
#ifndef NDEBUG
...
#endif
}
6.6 函数匹配
首先寻找候选函数(函数名),在寻找可行函数(参数)
6.7 函数指针
bool lengthCompare(const string&,const string&);
bool (*pf)(const string&,const string&);
pf=lengthCompare;//pf为函数指针,执行函数
1.函数指针形参
形参是函数则自动转换为函数指针
void useBigger(const string&,const string&,
bool pf(const string&,const string&));
//等价于
void useBigger(const string&,const string&,
bool (*pf)(const string&,const string&));
2.返回指向函数的指针
虽然不能返回一个函数,但可以返回指向函数的指针
//使用别名
using F=int(int*,int);
using PF=int(*)(int*,int);
PF f1(int);
F f1(int);//错误,不能返回函数
F *f1(int);
int (*f1(int))(int*,int);//直接声明
3.将auto和decltype用于函数执行类型
size_type sumLength(const string&,const string&);
decltype(sumLength) *getFcn(cons string&);