使人迷惑的寫法(五十六)

        今天咱們來看看一些在程序中迷惑的寫法,下面的程序想要表達什麼意思呢?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++ 編譯器中支持嗎?編程

圖片.png

        咱們看到編譯器編譯經過而且運行成功。那麼咱們不是用的 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 種解讀方式。那麼在這塊是否是就出現了二義性呢?咱們看看編譯結果圖片.png函數

        咱們看到編譯器直接報錯了,若是是一種類型的話,便讓咱們在前前面加上 typename,那麼咱們在模板中加上 typename,看看學習

圖片.png

        編譯器又報錯了,它說 Test_1 中沒有這種類型,確定沒有啊,只有一個成員變量而已。咱們註釋掉 Test_1 看看spa

圖片.png

        編譯經過了。那麼 typename 誕生的緣由是什麼呢?用來自定義類類型內部的嵌套類型,不一樣類中的同一個標識符可能致使二義性,編譯器沒法直接辨識標識符到底是什麼。typename 的做用有兩個:一、在模板定義中聲明泛指類型;二、明確告訴編譯器其後的標識符爲類型指針

        那麼下面的程序想要表達什麼意思呢?圖片

圖片.png

        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,而拋出了字符型異常。咱們來看看會致使程序運行終止嘛?

圖片.png

        確實致使了程序的運行終止了,注意咱們的程序中還有 catch(...) 都沒能捕捉到 char  類型的異常。那麼咱們在聲明的異常中加上 char 再來看看

圖片.png

        程序正常的運行結束了。經過今天對一些迷惑寫法的學習,總結以下:一、class 能夠用來在模板中定義泛指類型(不推薦);二、typename 是能夠消除模板中的二義性;三、try...catch 能夠將函數體分紅 2 部分;四、異常聲明可以提供程序的可讀性。


        歡迎你們一塊兒來學習 C++ 語言,能夠加我QQ:243343083

相關文章
相關標籤/搜索