令人迷惑的写法 一下面的程序想要表达什么意思呢?template< class T >class Test{public: Test(T t) { } };template < class T >void func(T a[], int len){}编程实验: class 模板初探#include <iostream>#include <string>using namespace std;template< class T >class Test{public: Test(T t) { cout << “t = " << t << endl; } };template < class T >void func(T a[], int len){ for(int i=0; i<len; i++) { cout << a[i] << endl; }}int main(){ Test<string> ts(“D.T.Software”); string ta[] = {“D”, “.”, “T”, “.”}; func(ta, 4); Test<int> ti(100); int ai[] = {1, 2, 3, 4}; func(ai, 4); return 0;}输出:【编译无错误,无警告】t = D.T.SoftwareD.T.t = 1001234分析:class 定义的类模板即可以适用于类类型,也可以适用于基础类型(等同于 typename)历史上的原因 。。。早期的 C++ 直接复用 class 关键字来定义模板但是泛型编程针对的不只是类类型class 关键字的复用使得代码出现二义性typename 诞生的直接原因自定义类类型内部的嵌套类型不同类中的同一个标识符可能导致二义性编译器无法辨识标识符究竟是什么编程实验: 模板中的二义性#include <iostream>#include <string>using namespace std;int a = 0;class Test_1{public: static const int TS = 1;};class Test_2{public: struct TS { int value; };};template < class T >void test_class(){ T::TS * a; // 解读方式 1 : 通过泛指类型 T 内部的数据类型 TS 定义指针变量 a (倾向的解读方式) // 解读方式 2 : 通过泛指类型 T 内部的静态成员变量 TS 与全局变量 a 进行乘法操作} int main(){ test_class<Test_1>(); test_class<Test_2>(); // Error return 0;}输出:test.cpp: In function ‘void test_class() [with T = Test_2]’:test.cpp:34: instantiated from heretest.cpp:27: error: dependent-name ‘T::TS’ is parsed as a non-type, but instantiation yields a typetest.cpp:27: note: say ‘typename T::TS’ if a type is meant结论:T::TS * a; ==> 编译器默认解析 TS 为成员变量#include <iostream>#include <string>using namespace std;int a = 0;class Test_1{public: static const int TS = 1;};class Test_2{public: struct TS { int value; };};template < class T >void test_class(){ typename T::TS * a; // 解读方式 1 : 通过泛指类型 T 内部的数据类型 TS 定义指针变量 a (倾向的解读方式) // 解读方式 2 : 通过泛指类型 T 内部的静态成员变量 TS 与全局变量 a 进行乘法操作} int main(){ test_class<Test_1>(); // Error test_class<Test_2>(); return 0;}输出:test.cpp: In function ‘void test_class() [with T = Test_1]’:test.cpp:33: instantiated from heretest.cpp:27: error: no type named ‘TS’ in ‘class Test_1’结论:typename T::TS * a; ==> 明确告诉编译器 typename 后为泛指类型typename 的作用在模板定义中声明泛指类型明确告诉编译器其后的标识符为类型令人迷惑的写法 二下面的程序想要表达什么意思呢?int func(int i) try{ return i;}catch(…){ cout << “Eception…” << endl;}int func(int i, int j) throw(int, char){ return i + j;}try … catch 用于分隔正常功能代码与异常功能代码try … catch 可以直接将函数分割为 2 部分函数声明和定义时可以直接指定可能抛出的异常类型异常声明成为函数的一部分可以提高代码可读性函数异常声明的注意事项函数异常声明是一种与编译器之间的锲约函数声明异常后就只能抛出声明的异常抛出其它类型异常将导致程序运行终止可以直接通过异常声明定义无异常函数编程实验: 新的异常写法#include <iostream>#include <string>using namespace std;int func(int i, int j) throw(int, char){ if( (0 < j) && (j < 10) ) { return (i + j); } else { throw ‘0’; }} void test(int i) try{ cout << “func(i, i) = " << func(i, i) << endl;}catch(int i){ cout << “Exception: " << i << endl;}catch(…){ cout << “Exception…” << endl;}int main(){ test(5); test(10); return 0;}输出:func(i, i) = 10Exception…小结class 可以用来在模板中定义泛指类型(不推荐)typename 可以消除模板中的二义性try… catch 可以将函数体分成 2 部分异常声明能够提高程序的可读性以上内容参考狄泰软件学院系列课程,请大家保护原创!