1. 程式人生 > >3. STL程式設計三

3. STL程式設計三

1. 演算法容器的使用:

#include <iostream>
#include <functional>
#include <vector>
#include <algorithm>    //演算法,共包含108個演算法
#include <numeric>        //整數

using namespace std;
using namespace std::placeholders;    //用於bind()函式的"_1"引數

struct MyStruct
{
    int operator()(int data)    //
對()進行過載-->偽函式 { return data % 2 == 1; } }; int get(int data) { return data % 2 == 1; } struct my { int get(int data) { return data % 2 == 1; } }; int main() { vector<int> myint{ 1,2,3,4,5,6,7,8,9,11 }; //建立容器 //法一:lambda表示式 int num1 = count_if(myint.begin(), myint.end(), [](int
data)->bool {return data % 2 == 0; }); //偶數個數 //法二:偽函式(匿名物件) int num2 = count_if(myint.begin(), myint.end(), MyStruct()); //MyStruct()匿名物件 //法三:有名物件 MyStruct my1; int num3 = count_if(myint.begin(), myint.end(), my1); //法四:函式 int num4 = count_if(myint.begin(), myint.end(), get
); //法五:成員函式(函式繫結器) my my2; auto fun = bind(&my::get, &my2, _1); int num5 = count_if(myint.begin(), myint.end(), fun); cout << num1 << endl; //4 cout << num2 << endl; //6 cout << num3 << endl; //6 cout << num4 << endl; //6 cout << num5 << endl; //6 system("pause"); return 0; }

    

   1.1 加入函式模板如下:

#include <iostream>
#include <functional>
#include <vector>
#include <algorithm>    //演算法,共包含108個演算法
#include <numeric>        //整數

using namespace std;
using namespace std::placeholders;    //用於bind()函式的"_1"引數

template<class T>
bool getT(T data)
{
    return data % 2 == 1;
}

int main()
{
    vector<int> myint{ 1,2,3,4,5,6,7,8,9,11 };    //建立容器

    int num6 = count_if(myint.begin(), myint.end(), getT<int>);
    cout << num6 << endl;    //6

    system("pause");
    return 0;
}

    

2. 模板的展開 ==> 屬於模板元的範疇

#include <iostream>
#include <cstdarg>
using namespace std;

template<class T>
void show(T t)
{
    cout << t << " ";
}

template<class...Args>
void all(Args...args)
{
    int arr[] = { (show(args),0)... };    //使用陣列進行展開
}

template<class...Args>
void allIt(Args...args)
{
    int arr[] = { (show(args),0)... };    //int arr[],用來約束展開多少層,儲存在數組裡面,[]不能省
}

int main()
{
    all(1, 2, 3, 4, 5);
    cout << endl;
    all(1, 2, 3, 4, 5, 6, 7, 8);
    cout << endl;
    allIt(1, 'A', "123", 7.89);
    cout << endl;

    system("pause");
    return 0;
}

    

3. 函式模板推理機制:

#include <iostream>
using namespace std;

template<typename T>    
void go(T t)    //將型別泛型
{
    cout << typeid(T).name() << endl;
    //cout << t << endl;
    cout << "T:" << endl;
}

template<int i>  //模板之間也可以過載
void go()        //資料可以為任意資料(相當於數字模板)
{
    cout << i << endl;
}

template<typename T>
void go(T *t)    //將型別泛型
{
    cout << typeid(T).name() << endl;
    cout << "T *:" << t << endl;
}

int main()
{
    /*
    go(31 - 2);                 //呼叫泛型函式模板

    go<31 - 2>();               //呼叫數字模板

    go<decltype(10 + 2)>(1234); //呼叫泛型函式模板,可以用decltype獲取資料型別
    */

    go(nullptr);                //nullptr不是指標型別,是一種自定義的資料型別表示空指標而已,呼叫go(T t)

    int *p = nullptr;           //呼叫go(T *t)
    go(p);

    system("pause");
    return 0;
}

    

4. 函式指標與函式模板:

  4.1 函式模板賦值給函式指標:

#include <iostream>
using namespace std;

template<class T>
void show(T t)
{
    cout << t << endl;
}

struct MyStruct
{
    template<class T>
    void show(T t)
    {
        cout << t << endl;
    }

    void go()        
    {
        show(123);
    }
};

//函式模板賦值給函式指標
int main()
{
    //void(*p)() = show<int>;    //無法從“void (__cdecl *)(T)”轉換為“void (__cdecl *)(void)”
    void(*p1)(int i) = show<int>;
    void(*p2)(double db) = show<double>;

    system("pause");
    return 0;
}

  4.2 如何呼叫結構體中的函式模板?

//如何呼叫結構體中的函式模板?
int main()
{
    MyStruct my1;
    my1.go();            //結構體內部呼叫結構體中的函式模板

    my1.show(12.3);      //外部直接呼叫結構體中的函式模板
    my1.show('A');
    my1.show<int>('A');

    system("pause");
    return 0;
}

    

  4.3 如何繫結結構體內部的函式模板?

#include <iostream>
#include <functional>

using namespace std;
using namespace std::placeholders;

template<class T>
void show(T t)
{
    cout << t << endl;
}

struct MyStruct
{
    template<class T>
    void show(T t)
    {
        cout << t << endl;
    }

    template<class T>
    void showit(T t1, T t2)
    {
        cout << t1 << " " << t2 << endl;
    }

    void go()        
    {
        show(123);
    }
};

//如何繫結結構體內部的函式模板?
int main()
{
    MyStruct my1;
    auto fun = bind(&MyStruct::showit<int>, &my1, 1, 2);
    fun(2);

    system("pause");
    return 0;
}

    

5. 函式模板、模板函式與類模板:

  5.1 什麼是函式模板?什麼是模板函式?

    函式模板就是上面所講的函式模板,而模板函式則是例項化的函式模板

#include <iostream>
using namespace std;

/*函式模板,不呼叫不編譯*/
template<class T>
T add(T a, T b)
{
    return a + b;
}

int main()
{
    add(1, 2);              /*模板函式,也就是例項化的函式模板,自動根據引數推理*/
    add<double>(1, 1.2);    /*模板函式*/

    system("pause");
    return 0;
}

  5.2 類成員函式模板:

#include <iostream>
using namespace std;

class myclass
{
public:
    template<class T>        //類成員函式模板
    T add(T a, T b)
    {
        return a + b;
    }

    template<class T>        //靜態函式模板
    static T sub(T a, T b)
    {
        return a - b;
    }
};

int main()
{
    myclass *p = nullptr;
    int num1 = p->add<int>(2, 3);   //強行指定的模板函式,當做類成員函式呼叫
    int num2 = p->add(2, 3);        //自動推理的模板函式
    cout << num1 << endl;
    cout << num2 << endl;

    int num3 = myclass::sub(9 , 1);
    cout << num3 << endl;

    system("pause");
    return 0;
}

    

6. 模板在類中的應用:

#include <iostream>
#include <cstdlib>
using namespace std;

class myclass
{
public:
    template<class T>
    T add(T a)
    {
        return a;
    }

    template<class T>
    T add(T a,T b)
    {
        show();            //函式模板與類成員函式可以互相呼叫
        return a + b;
    }

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

    //template<class T>
    //virtual T add(T a, T b,T c)        //error C2898: “T myclass::add(T,T,T)”: 成員函式模板不能是虛擬的
    //{
    //    return a + b + c;
    //}

    void show()
    {
        cout << add<int>(10) << endl;    //指明型別的方式呼叫
    }

};

int main()
{
    myclass *p = nullptr;
    p->add(1, 2);

    system("pause");
    return 0;
}

7. 類模板與函式模板對比:

#include <iostream>
#include <initializer_list>
#include <memory>
#include <string>
using namespace std;

template<class T,int n>
class myarray
{
    T *p;
public:
    myarray(initializer_list<T> mylist)
    {
        p = new T[n];                //開闢記憶體
        memset(p, 0, sizeof(T)*n);   //記憶體清0
        
        int length = mylist.size();
        if (length > n)
        {
            abort();    //觸發異常
        }
        else
        {
            int i = 0;
            for (auto j : mylist)    //資料填充
            {
                p[i] = j;
                i++;
            }
        }
    }

    ~myarray()
    {
        delete[] p;
    }

    void show()    //顯示資料
    {
        for (int i = 0; i < n; i++)
        {
            cout << p[i] << " ";
        }
        cout << endl;
    }

    void sort()    //氣泡排序
    {
        for (int i = 0; i < n - 1; i++)
        {
            for (int j = 0; j < n - 1 - i; j++)
            {
                if (p[j] < p[j+1])    //從大到小
                {
                    T temp = p[j];
                    p[j] = p[j + 1];
                    p[j + 1] = temp;
                }
            }
        }
    }
};

int main()
{
    myarray<int, 10> my1 = { 1,2,3,4,5,6,7,8,9 };
    my1.show();
    my1.sort();
    my1.show();

    myarray<double, 5> my2 = { 1.1,2.2,3.3,4.4,5.5 };
    my2.show();
    my2.sort();
    my2.show();

    myarray<string, 5> my3 = { "123","abcdef","sdaf","hello" };
    my3.show();
    my3.sort();
    my3.show();

    system("pause");
    return 0;
}

    

8. 類包裝器:

#include <iostream>
using namespace std;

template<class T,class F>    //函式模板
T run(T t, F f)
{
    return f(t);
}

class fun
{
public:
    double operator ()(double data)
    {
        return data - 10;
    }

};

template<class T>    //類模板
class Tfun
{
public:
    T operator ()(T data)
    {
        return data - 10;
    }

};

int main()
{
    cout << run(10.9, fun()) << endl;            //fun()是匿名物件
    fun x;
    cout << run(10.9, x) << endl;                //x是有名物件

    cout << run(10.9, Tfun<double>()) << endl;   //模板函式的匿名物件,建構函式返回的就是匿名物件
    Tfun<double> fang;
    cout << run(10.9, fang) << endl;

    system("pause");
    return 0;
}

    

9. 高階類包裝器:

#include <iostream>
#include <list>
#include <vector>
using namespace std;

template<class T, class F>    //函式模板
T run(T t, F f)
{
    return f(t);
}

template<class T>    //類模板
class Trun
{
public:
    T operator ()(T data)
    {
        for (auto i:data)
        {
            cout << i <<" ";
        }
        cout << endl;
        return data;
    }

};

int main()
{
    list<int> myint;    //構建連結串列,壓入資料
    for (int i = 0; i < 5; i++)
    {
        myint.push_back(i);
    }

    run(myint,                            //lambda表示式
        [](list<int> myint)->list<int> 
        {
            for (auto i : myint)
            {
                cout << i << endl;
            }
            return myint;
        }
        );

    system("pause");
    return 0;
}

    

#include <iostream>
#include <list>
#include <vector>
using namespace std;

template<class T, class F>    //函式模板
T run(T t, F f)
{
    return f(t);
}

template<class T>    //類模板
class Trun
{
public:
    T operator ()(T data)
    {
        for (auto i:data)
        {
            cout << i <<" ";
        }
        cout << endl;
        return data;
    }

};

int main()
{
    vector<int> myv{ 1,2,3,4,5,7,8 };
    run(myv, Trun< vector<int> >());    //匿名物件,用完就扔
    run(myv, Trun< decltype(myv) >());

    system("pause");
    return 0;
}

    

 10. 類模板間的封裝、繼承、多型:

  10.1 父類為類模板,子類也是類模板:

#include <iostream>
using namespace std;

//類模板支援封裝、繼承、多型
template<class T>
class Tfu
{
public:
    T t;
    Tfu():t(0)
    {
    }

    void show()
    {
        cout << t << endl;
    }

    virtual void go()
    {
        cout << "fu:" << t << endl;
    }
};

template<class T>
class Tzi :public Tfu<T>
{
public:    
    void go()
    {
        cout << "zi:" << t << endl;
    }
};

int main()
{
    Tzi<int> tzi;
    tzi.t = 109;
    tzi.show();

    Tfu<int> *p = new Tzi<int>;    //實現多型
    p->go();

    system("pause");
    return 0;
}

    

  10.2 父類為類模板,子類為普通類:

#include <iostream>
using namespace std;

template<class T>
class Tfu
{
public:
    T t;
    Tfu() :t(0)
    {
    }

    void show()
    {
        cout << t << endl;
    }

    virtual void go()
    {
        cout << "fu:" << t << endl;
    }
};

class zi :public Tfu<int>
{
public:
    void go()
    {
        cout << "zi:" << t << endl;
    }
};

int main()
{
    zi z1;
    z1.t = 108;
    z1.show();

    Tfu<int> *p = new zi;    //多型    此處只能用int
    p->go();

    system("pause");
    return 0;
}

    

  10.3  父類為普通類,子類為類模板:

#include <iostream>
using namespace std;

//類模板支援封裝、繼承、多型

//T    T    //類模板        可以實現封裝、繼承、多型
//T    P    //類模板與類    可以實現封裝、繼承、多型    必須明確型別
//P    T    //類與類模板    可以實現封裝、繼承、多型    必須明確型別    多型什麼型別都可以
//P    P    //普通類        可以實現封裝、繼承、多型
class die
{
public:
    int t;
    die() :t(0)
    {
    }

    void show()
    {
        cout << t << endl;
    }

    virtual void go()
    {
        cout << "fu: " << t << endl;
    }
};

template<class T>
class er :public die
{
public:
    void go()
    {
        cout << typeid(T).name() << "   zi: " << t << endl;
    }

};

int main()
{
    er<double> boer;
    boer.show();

    die *p1 = new er<char>;
    die *p2 = new er<int>;
    die *p3 = new er<double>;
    p1->go();
    p2->go();
    p3->go();

    system("pause");
    return 0;
}