第68课.拾遗:令人迷惑的写法

1.typename和class

早期c++直接复用class关键字来定义模板,但是class关键字的复用使得代码出现二义性。这时才诞生了typename来代替class。

eg:

#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 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(int argc, char *argv[])
{
    // test_class<Test_1>();
    test_class<Test_2>();
    
    return 0;
}

typename的作用:

a.在模板定义中声明泛指类型
b.明确告诉编译器其后的标识符为类型

2.try...catch...与throw...

a.try...catch用于分隔正常功能代码与异常处理代码
b.try...catch可以直接将函数分隔为2部分
c.函数声明和定义时可以直接指定可能抛出的异常类型
d.异常声明成为函数的一部分可以提高代码可读性

函数异常声明的注意事项

a.函数异常声明是一种与编译器之间的契约
b.函数声明异常后就只能抛出声明的异常
1).抛出其他异常将导致程序运行终止
2).可以直接通过异常声明定义无异常函数

eg:

#include <iostream>
#include <string>

using namespace std;

int func(int i, int j) throw(int, char)        // 能抛出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(int argc, char** argv)
{
    test(5);
    test(10);
    
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/huangdengtao/p/12040012.html