3. STL編程三

1. 算法容器的使用:ios

#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. 函數指針與函數模板:spa

  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 如何調用結構體中的函數模板?code

//如何調用結構體中的函數模板?
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. 函數模板、模板函數與類模板:blog

  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;
}

    

相關文章
相關標籤/搜索