当前位置 主页 > 网站技术 > 代码类 >

    C++ 泛型编程详解(2)

    栏目:代码类 时间:2020-02-06 21:08

    // 函数模板
    template<typename T> 
    void tfunc(const T& t) {
     cout << "template: " << t << endl;
    }
    
    // 函数模板实例化,不用写函数的实现,编译器会生成该类型的模板具体化函数
    template void tfunc<char>(const char& c);
    

    类模板

    类模板可以指定默认模板参数(函数模板不可以),跟函数参数的默认值一样,必须从右向左连续赋值默认类型,如果实例化对象时又传递了类型,默认类型会被覆盖掉,跟函数参数是一样的
    创建对象时需要传递模板参数列表,模板参数列表加在类名后面 ClassName< typename T > classN; 如果类的模板参数列

    表有默认值,可以不传模板参数,但一定要加 <> 如 ClassName< > classN; 创建堆区对象的时候,所有的类名称后面都要加模板参数列表,如 ClassName< typename T >* classN = new ClassName< typename T>; 除了类内,其他地方出现 ClassName 的地方一般都要加模板参数列表

    template<typename T = int, typename Y = char> // 此处指定了模板默认参数,部分指定必须从右到左指定
    class Test {
    public:
     Test(T t, Y y) : t(t), y(y) {
     }
     void tfunc();
    private:
     T t;
     Y y;
    };
    template<typename T, typename Y> // 类模板的函数在类外实现,需要加上模板参数列表,但不需要加指定的默认模板参数
    void Test<T, Y>::tfunc() { // 类外使用Test需要加模板参数
     cout << t << " " << y << endl;
    }
    int n = 2;
    double d = 2.1;
    Test<int, double> test(n, d); // 此处如果使用默认模板参数可定义为 Test<> test(int(2), char('a'));
    test.tfunc();
    // 运行结果:2 2.1

    类模板的继承,类模板被继承后参数的传递方式主要有两种,一种是直接在子类继承父类的时候,为父类指定固定的类型,二是通过子类模板参数列表传递

    // ====== 测试一 ======
    template<typename T, typename Y>
    class A {
    public:
     A(T t, Y y) {
     }
    };
    class Test : public A<int, double> { // 父类是类模板,子类是普通类
    public:
     Test() : A<int, double>(2, 2.1) {
     }
    };
    Test();
    // ====== 测试二 ======
    template<typename T, typename Y>
    class A {
    public:
     A(T t) {
     }
    };
    template<typename X, typename Z, typename P>
    class Test : public A<X, P> {
    public:
     Test(X x, Z z, P p) : A<X, P>(x) {
     }
    };
    Test<int, double, char>(int(2), double(2.1), char('a'));

    类模板的多态,在创建对象时,分为子类没有模板(CFather<short, char>*cf = new CSon;)和子类有模板(CFather<short, char> *cf = new CSon<short, int, char>)两种,子类和父类的模板参数列表可以不一样,但一定要对应好

    // ====== 测试一 ======
    template<typename T, typename Y> 
    class A {
    public:
     virtual void tfunc(T t, Y y) = 0;
    };
    class Test : public A<int, double> { 
    public:
     virtual void tfunc(int n, double d) {
     cout << n << " " << d << endl;
     }
    };
    // 父类是类模板,子类是普通类,在多态情况下父类需要指定模板参数,子类就不用了
    A<int, double>* a = new Test;
    a->tfunc(2, 2.1);
    // 运行结果:2 2.1
    // ====== 测试二 ======
    template<typename T, typename Y> 
    class A {
    public:
     virtual void tfunc(T t, Y y) = 0;
    };
    template<typename X, typename Z, typename P>
    class Test : public A<X, P> {
    public:
     virtual void tfunc(X x, P p) {
     cout << x << " " << p << endl;
     }
    };
    
    // 父类是类模板,子类是类模板,在多态情况下父类和子类都需要指定模板参数
    A<int, double>* a = new Test<int, char, double>;
    a->tfunc(2, 2.1);
    // 运行结果:2 2.1