zoukankan      html  css  js  c++  java
  • 第68课 拾遗,令人迷惑的写法

    令人迷惑的写法:

    示例程序:

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

    有了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 }

    结果如下:

    小结:

  • 相关阅读:
    Android中ProgressBar显示小数的方法
    Android屏幕适配-安卓切图
    android -services
    Java 位移运算符
    异常、集合、数据结构
    常用类
    编码
    String类
    Android-1
    ButterKnife注解式绑定控件
  • 原文地址:https://www.cnblogs.com/wanmeishenghuo/p/9601768.html
Copyright © 2011-2022 走看看