今天咱们来看看一些在程序中迷惑的写法,下面的程序想要表达什么意思呢?ios
#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() { int a[5] = {1, 2, 3, 4, 5}; Test<int> t(5); cout << endl; func(a, 5); return 0; }
咱们在类模板中用 class 来声明,可是咱们在 main 函数中是用 int 类型来使用的,下来咱们看看这样的写法在 C++ 编译器中支持吗?编程
咱们看到编译器编译经过而且运行成功。那么咱们不是用的 typename 来声明的泛指类型的嘛,这怎么用 class 了呢。这是由于历史上的一些缘由,早期的 C++ 直接复用 class 关键字来定义模板,可是泛型编程针对的不仅是类类型,class 关键字的复用使得代码出现二义性。下来咱们来看看具备二义性的代码ide
#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>(); return 0; }
咱们经过在函数模板指定泛指类型为 Test_1,即是第 2 种解读方式,泛指类型为 Test_2 时,即是第 1 种解读方式。那么在这块是否是就出现了二义性呢?咱们看看编译结果函数
咱们看到编译器直接报错了,若是是一种类型的话,便让咱们在前前面加上 typename,那么咱们在模板中加上 typename,看看学习
编译器又报错了,它说 Test_1 中没有这种类型,确定没有啊,只有一个成员变量而已。咱们注释掉 Test_1 看看spa
编译经过了。那么 typename 诞生的缘由是什么呢?用来自定义类类型内部的嵌套类型,不一样类中的同一个标识符可能致使二义性,编译器没法直接辨识标识符到底是什么。typename 的做用有两个:一、在模板定义中声明泛指类型;二、明确告诉编译器其后的标识符为类型。指针
那么下面的程序想要表达什么意思呢?图片
try...catch 用于分隔正常功能代码与异常处理代码,try...catch 能够直接将函数实分隔为两部分。函数声明和定义时能够直接指定可能抛出的异常类型,异常声明成为函数的一部分能够提升代码可读性。那么函数异常声明时有几个注意事项:一、函数异常声明是一种与编译器之间的契约;二、函数声明异常后就只能抛出声明的异常,抛出其余异常将致使程序运行终止,能够直接经过异常声明定义无异常函数。编译器
下来咱们仍是以代码为例来进行说明string
#include <iostream> #include <string> using namespace std; int func(int i, int j) throw(int) { 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 函数中异常只声明了 int,而抛出了字符型异常。咱们来看看会致使程序运行终止嘛?
确实致使了程序的运行终止了,注意咱们的程序中还有 catch(...) 都没能捕捉到 char 类型的异常。那么咱们在声明的异常中加上 char 再来看看
程序正常的运行结束了。经过今天对一些迷惑写法的学习,总结以下:一、class 能够用来在模板中定义泛指类型(不推荐);二、typename 是能够消除模板中的二义性;三、try...catch 能够将函数体分红 2 部分;四、异常声明可以提供程序的可读性。
欢迎你们一块儿来学习 C++ 语言,能够加我QQ:243343083。