19. C++第十六節到十八節的總結

你可能會看到類似下面的模板定義:

#include <cstdlib>
#include <iostream>

using namespace std;

template<class T>
T Minus(T a, T b)
{
    return a - b;
}

template<class T>
class Add
{
public:
    T add(T a, T b)
    {
        return a + b;
    }
};

int main(int argc, char *argv[])
{
    cout<<Minus(3, 4)<<endl;
    cout<<Minus<float>(0.3, 0.4)<<endl;
    
    Add<double> ap;
    
    cout<<ap.add(9, 8)<<endl;
    cout<<ap.add(0.001, 0.1)<<endl;
    
    cout << "Press the enter key to continue ...";
    cin.get();
    return EXIT_SUCCESS;
}

編譯運行結果如下:

爲什麼class可以用來定義模板參數呢?爲什麼還要引進typename呢?

 

在類中可以定義其它的新類型

#include <cstdlib>
#include <iostream>

using namespace std;

class Test
{
public:
    typedef int* PINT;
    
    struct Point
    {
        int x;
        int y;
    };
    
    class Sub
    {
        public:
            Sub()
            {
                cout<<"Sub()"<<endl;
            }
            
            void print()
            {
                cout<<"Hello World"<<endl;
            }
    };
};

int main(int argc, char *argv[])
{
    Test::PINT pi = new int(5);
    Test::Point po = {2, 3};
    Test::Sub sub;
    
    cout<<*pi<<endl;
    cout<<po.x<<" "<<po.y<<endl;
    
    sub.print();
    
    delete pi;
    
    cout << "Press the enter key to continue ...";
    cin.get();
    return EXIT_SUCCESS;
}

編譯運行結果如下:

 

在類模板中定義新的類型

在函數模板中使用類模板的內部類型

#include <cstdlib>
#include <iostream>

using namespace std;

template<typename T, int N>
class Test
{
public:
    typedef T ElemType;
    enum { LEN = N };
    
    ElemType array[LEN];
};

template<typename T>
void test_copy(T& test, typename T::ElemType a[], int len)
{
    int l = (len < T::LEN) ? len : T::LEN;
    
    for(int i=0; i<l; i++)
    {
        test.array[i] = a[i];
    }
}

int main(int argc, char *argv[])
{
    Test<int, 5> t1;
    Test<float, 3> t2;
    
    int ai[] = {5, 4, 3, 2, 1, 0};
    float af[] = {0.1, 0.2, 0.3};
    
    test_copy(t1, ai, 6);
    test_copy(t2, af, 3);
    
    for(int i=0; i<5; i++)
    {
        cout<<t1.array[i]<<endl;
    }
    
    for(int i=0; i<Test<float, 3>::LEN; i++)
    {
        cout<<t2.array[i]<<endl;
    }
    
    cout << "Press the enter key to continue ...";
    cin.get();
    return EXIT_SUCCESS;
}

編譯運行結果如下:

 

爲什麼class可以用來定義模板參數呢?爲什麼還要引進typename呢?

1. 模板最初的目標只是爲了對類類型進行泛型操作的定義,因此用class關鍵字聲明泛型類型;
       2. 在之後的進化過程中發現了模板相互調用時產生的 :: 操作符的二義性;
       3. 因此引入typename關鍵字是用於告訴編譯器將 :: 符號後的標識符看作類型;

 

寫個函數判斷一個變量是否爲指針嗎?

 

C++編譯器匹配示例

#include <cstdlib>
#include <iostream>

using namespace std;

int test(int i, int j)
{
    cout<<"int test(int i, int j)"<<endl;
}

template<typename T>
T test(T i, T j)
{
    cout<<"T test(T i, T j)"<<endl;
}

int test(...)
{
    cout<<"int test(...)"<<endl;
}

int main(int argc, char *argv[])
{
    int i = 0;
    int j = 0;
    
    test(i, j);
    
    cout << "Press the enter key to continue ...";
    cin.get();
    return EXIT_SUCCESS;
}

編譯運行結果如下:

 

函數模板與可變參數函數的化學反應

#include <cstdlib>
#include <iostream>

using namespace std;

template<typename T>
void isPtr(T*)
{
    cout<<"void isPtr(T*)"<<endl;
}

void isPtr(...)
{
    cout<<"void isPtr(...)"<<endl;
}

int main(int argc, char *argv[])
{
    int* pi = NULL;
    float* pf = NULL;
    int i = 0;
    int j = 0;
    
    isPtr(pi);
    isPtr(pf);
    isPtr(i);
    isPtr(j);
    
    cout << "Press the enter key to continue ...";
    cin.get();
    return EXIT_SUCCESS;
}

編譯運行結果如下:

 

解決方案1

#include <cstdlib>
#include <iostream>

using namespace std;

template<typename T>
bool isPtr(T*)
{
    return true;
}

bool isPtr(...)
{
    return false;
}

int main(int argc, char *argv[])
{
    int* pi = NULL;
    float* pf = NULL;
    int i = 0;
    int j = 0;
    
    cout<<isPtr(pi)<<endl;
    cout<<isPtr(pf)<<endl;
    cout<<isPtr(i)<<endl;
    cout<<isPtr(j)<<endl;
    
    cout << "Press the enter key to continue ...";
    cin.get();
    return EXIT_SUCCESS;
}

編譯運行結果如下:

 

你的方法實現了指針的判斷,但是我覺得不夠高效,你有更好的辦法嗎?

解決方案1已經很好的解決問題,那麼爲什麼還不夠高效呢?哪裏不夠高效呢?

解決方案1中唯一耗時的地方在於函數調用的建棧與退棧過程,因此需要考慮如何避免這個過程以提高程序效率。
 

解決方案2

#include <cstdlib>
#include <iostream>

using namespace std;

template<typename T>
char isPtr(T*);

int isPtr(...);

#define ISPTR(v) (sizeof(isPtr(v)) == sizeof(char))

int main(int argc, char *argv[])
{
    int* pi = NULL;
    float* pf = NULL;
    int i = 0;
    int j = 0;
    
    cout<<ISPTR(pi)<<endl;
    cout<<ISPTR(pf)<<endl;
    cout<<ISPTR(i)<<endl;
    cout<<ISPTR(j)<<endl;
    
    cout << "Press the enter key to continue ...";
    cin.get();
    return EXIT_SUCCESS;
}

編譯運行結果如下:

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章