关于默认的函数参数,有一条规则:
void defFunc(int i ,int j = 2,int k = 3) {
}
那就是默认实参必须在形参的右边.
为什么要这么规定? 其实我们调用一下代码就可以发现,必须这样:
defFunc(1); 默认等于 defFunc(1,2,3)
defFunc(1,8); 默认等于 defFunc(1,8,3)
如果不把默认实参放到形参的右边,那么我们的函数很可能就是:
defFunc("默认参数" ,2,3)
很显然我们就得引入一个标志,告诉编译器这里是一个默认参数.
今天我们要重点讲的是,函数模板和类模板默认模板参数类型的规则:
C++98开始支持引入函数模板和类模板,并且支持类模板的默认类型,但是C++98这个时候还不支持,函数模板默认类型. C++ 11引入了此规则.
template <typename T = int> void defFunc(T a) { //C++ 98不合法,C++ 11合法
}//可以这么写,但是没有什么意义,呵呵!自己想.
类模板默认参数类型和函数默认参数拥有一样的规则:默认实参类型必须在形参的右边.
template<class T, class T1 = int, class T2 = string> class myclass{ //合法
};
以下写法是不合法的.
template<class T = int, class T1 , class T2 = string> class myclass2 { //不合法
};
原因其实和默认函数参数实参类型必须在形参右边是一样的。
类模板本身是一个大家族,模板类是一个具体的大家族中的成员,类似具体下面模板类的写法:
myclass<int ,double ,string> m1;
只是
myclass<T1,T2,T3>类模板中的一员而已.
和函数同样的理由,如果不这么做,那么我们可以就必须引入一个标志,告诉编译器这是个默认类型,那么就失去默认类型的意义了.
但是再想想,为什么函数参数却不需要遵守这个规则了呢??
肯定是由于某种原因,导致了此规则被破坏.
答案是:函数模板参数类型,编译器支持默认类型的推导。
举个例子:
template<typename T1, typename T2> void func(T1 t1, T2 t2) {
cout << t1 << endl;
cout << t2 << endl;
}
编译器能够根据函数的参数类型自动推导出模板函数,但是模板类就不行,编译器没法自动帮模板类做参数类型的匹配。
下面的模板函数,默认参数类型就是
template<typename T1 = int, typename T2, typename T3> void func2(T2 t2,T3 t3,T1 t1 = 0) {
cout << t1 << endl;
cout << t2 << endl;
cout << t2 << endl;
}
在函数中,可以看到默认的模板类型是不需要遵守必须在右边的规定的.
因为编译器也能够很轻松的推导出。