令人迷惑的写法:

 

示例程序:

上述程序可以正常编译通过。

有了class,为什么还要定义typename呢?

 

用class定义普通类型的泛指类型,容易产生迷惑性。

由于一个二义性问题,产生了typename:

示例程序:

第57行使用Test_1作为类型参数来使用模板可以编译通过,这意味着第50行被解释成了乘法操作。因为Test_1这个类种的TS是一个常量。

添加Test_2测试:

第58行使用Test_2作为类型参数来使用模板出错了,编译器报错显示,在第50行,我们更倾向于让TS作为一个类型来使用,如果是这样的话我们必须使用typename关键字来说明一下。 

第50行的写法,编译器默认TS是一个静态成员变量,而不是一个类型。这与我们的第一反应相违背。

于是,typename就诞生了,一个作用是用于在模板里面定义泛指类型,另一个作用就是解决这里的二义性问题。

 完善程序:

 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 
 6 template < class T >
 7 class Test
 8 {
 9 public:
10     Test(T t) 
11     { 
12         cout << "t = " << t << endl;
13     }
14 };
15 
16 template < class T >
17 void func(T a[], int len)
18 {
19     for(int i=0; i<len; i++)
20     {
21         cout << a[i] << endl;
22     }
23 }
24 
25 
26 //////////////////////////////////////////////////////////////
27 //////////////////////////////////////////////////////////////
28 
29 int a = 0;
30 
31 class Test_1
32 {
33 public:
34     static const int TS = 1;
35 };
36 
37 class Test_2
38 {
39 public:
40     struct TS
41     {
42         int value;
43     };
44 };
45 
46 template
47 < class T >
48 void test_class()
49 {
50     typename T::TS * a;        // 1. 通过泛指类型 T 内部的数据类型 TS 定义指针变量 a (推荐的解读方式)
51                                // 2. 使用泛指类型 T 内部的静态成员变量 TS 与全局变量 a 进行乘法操作
52 }
53 
54 
55 int main(int argc, char *argv[])
56 {
57     // test_class<Test_1>();
58     test_class<Test_2>();
59     
60     return 0;
61 }

 

 typename诞生的原因:

 

 

令人迷惑的写法2:

这里的try是放在函数之外的,这在之前是没有见过的,将一个函数实现分为两部分,try是正常逻辑部分,catch是异常逻辑部分。

上图中右边的函数告诉编译器,我们这个函数是可能抛出异常的,异常类型是int。这就是异常声明,是函数可选部分,增加了函数的可读性,让别人知道这个函数可能抛出异常。

 

异常声明的注意事项:

 

新的异常写法:

 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 
 6 int func(int i, int j) throw(int, char)
 7 {
 8     if( (0 < j) && (j < 10) )
 9     {
10         return (i + j);
11     }
12     else
13     {
14         throw '0';
15     }
16 }
17 
18 void test(int i) try
19 {
20     cout << "func(i, i) = " << func(i, i) << endl;
21 }
22 catch(int i)
23 {
24     cout << "Exception: " << i << endl;
25 }
26 catch(...)
27 {
28     cout << "Exception..." << endl;
29 }
30 
31 
32 int main(int argc, char *argv[])
33 {
34     test(5);
35     
36     test(10);
37     
38     return 0;
39 }

结果如下:

 

小结:

 

posted on 2018-09-06 22:52  周伯通789  阅读(280)  评论(0编辑  收藏  举报