类模板

作者: arkliu | 来源:发表于2022-11-28 09:21 被阅读0次

    类模板的基本语法

    • 类模板必须显示指定类型,无法根据参数值来推导类型变量。
    #include <iostream>
    
    using namespace std;
    
    template<class T>
    class Person {
        public:
            T m_id;
            T m_age;
    
            Person(T id, T age) {
                this->m_age = age;
                this->m_id = id;
            }
    
            void show() {
                cout << "id = "<< m_id << "  age = "<< m_age << endl;
            }
    
            static void static_show() {
                cout << "static_show run.." << endl;
            }
    };
    
    int main() {
        // 类模板必须显示指定类型
        Person<int> p(22, 33);
        p.show();
        p.static_show();
    
        Person<int>::static_show();
        return 0;
    }
    
    

    为类模板指定默认的类型

    • 默认值要放在最后面
    #include <iostream>
    
    using namespace std;
    
    template<class T1, class T2=string>
    class AA {
        private:
            T1 age;
            T2 name;
        public:
            AA(T1 age, T2 name="tom") {
                    this->age = age;
            }
    
    };
    int main() {
        AA<int>aa1(12);
        AA<int,double>aa2(33, 4.56);
        return 0;
    }
    
    

    类模板具体化

    首先去写 “①全特化”,然后再实现 “②普通类模板”,否则会出现"error: ‘XXX’ is not a class template" 错误。

    #include <iostream>
    #include<string>
    using namespace std;
    
    template<class T1, class T2>
    class AA {
        private:
            T1 m_age;
            T2 m_name;
        public:
            AA(T1 age, T2 name):m_age(age),m_name(name) {
                cout <<"类模板构造函数..."<<endl;
            }
            void show()const;
    };
    
    template<class T1, class T2>
    void AA<T1,T2>::show() const{
        cout <<"类模板show函数..."<<endl;
    }
    
    template<>
    class AA<int,string> {
        private:
            int m_age;
            string m_name;
        public:
            AA(int age, string name):m_age(age),m_name(name) {
                cout <<"类完全具体化构造函数..."<<endl;
            }
            void show()const;
    };
    
    void AA<int,string>::show() const{
        cout <<"类完全具体化show函数..."<<endl;
    }
    
    template<class T1>
    class AA<T1,string> {
        private:
            T1 m_age;
            string m_name;
        public:
            AA(T1 age, string name):m_age(age),m_name(name) {
                cout <<"类部分具体化构造函数..."<<endl;
            }
            void show()const;
    };
    
    template<class T1>
    void AA<T1,string>::show() const{
        cout <<"类部分具体化show函数..."<<endl;
    }
    
    int main() {
        AA<int,double>aa2(33, 4.56);
        return 0;
    }
    

    类模板派生普通类

    #include <iostream>
    #include<string>
    using namespace std;
    
    template<class T>
    class Person {
        public:
            T m_id;
            T m_age;
            Person(T id, T age):m_id(id),m_age(age) {
                cout <<"Person构造函数运行..."<<endl;
            }
            void show2() {
                cout <<"SubPerson show2 m_id "<<m_id<<"  m_age "<<m_age<<endl;
            }
    };
    
    // 用类定义对象,需要编译器分配内存,所以这里需要确定类型
    class SubPerson: public Person<int> {
        public:
            string m_name;
            SubPerson(string name, int id, int age):Person(id,age),m_name(name) {
                cout <<"SubPerson构造函数运行..."<<endl;
            }
            void show1() {
                cout <<"SubPerson show1 m_name "<<m_name<<endl;
            }
    };
    
    int main() {
        SubPerson subperson("张三", 12, 22);
        subperson.show1();
        subperson.show2();
    
        Person<int>subperson2(22, 34);
        subperson2.show2();
        return 0;
    }
    

    类模板派生类模板

    #include <iostream>
    
    using namespace std;
    
    template<class T>
    class Animal {
        public:
            T m_age;
    
            void speak() {
                cout << m_age <<"  is speaking.." << endl;
            }
    };
    
    template<class T>
    class Dog: public Animal<T> {
    
    };
    
    int main() {
        Dog<int> Dog;
        return 0;
    
    }
    
    

    模板类继承模板参数给出的基类

    #include <iostream>
    #include<string>
    using namespace std;
    
    class AA {
        public:
            AA() {cout <<"调用了AA的构造函数AA()"<<endl;}
            AA(int a) {cout <<"调用了AA的构造函数AA(int a)"<<endl;}
    };
    class BB {
        public:
            BB() {cout <<"调用了BB的构造函数BB()"<<endl;}
            BB(int b) {cout <<"调用了BB的构造函数BB(int b)"<<endl;}
    };
    class CC {
        public:
            CC() {cout <<"调用了CC的构造函数CC()"<<endl;}
            CC(int c) {cout <<"调用了CC的构造函数CC(int c)"<<endl;}
    };
    
    template<class T>
    class DD {
        public:
            DD() {cout <<"调用了DD的构造函数DD()"<<endl;}
            DD(int d) {cout <<"调用了DD的构造函数DD(int d)"<<endl;}
    };
    
    template<class T>
    class EE :public T{
        public:
            EE() {cout <<"调用了EE的构造函数EE()"<<endl;}
            EE(int e) {cout <<"调用了EE的构造函数EE(int e)"<<endl;}
    };
    
    int main() {
        EE<AA>e1;
        EE<BB>e2;
        EE<CC>e3;
        EE<DD<int>>e4;
        return 0;
    }
    

    类模板类内实现

    #include<iostream>
    
    using namespace std;
    
    template<class T1, class T2>
    class Person {
        public:
            T1 m_name;
            T2 m_age;
    
            Person(T1 name, T2 age) {
                this->m_name = name;
                this->m_age = age;
            }
            void show() {
                cout << "age = "<< m_age << "  name = "<<m_name << endl;
            }
    };
    
    int main() {
        Person<string, int>p("张三", 33);
        p.show();
        return 0;
    }
    
    

    类模板类外实现

    #include<iostream>
    
    using namespace std;
    
    template<class T1, class T2>
    class Person {
        public:
            T1 m_name;
            T2 m_age;
    
            Person(T1 name, T2 age);
            void show();
    };
    
    template<class T1, class T2>
    Person<T1, T2>::Person(T1 name, T2 age) {
        this->m_name = name;
        this->m_age = age;
    }
    template<class T1, class T2>
    void Person<T1, T2>::show() {
        cout << "age = "<< m_age << "  name = "<<m_name << endl;
    }
    
    int main() {
        Person<string, int>p("张三", 33);
        p.show();
        return 0;
    }
    
    

    类模板和静态成员

    #include<iostream>
    
    using namespace std;
    
    template<class T1>
    class Person {
        public:
            static int a;
    };
    
    //类外初始化
    template<class T1> int Person<T1>::a = 10;
    
    int main() {
        Person<int> p1, p2, p3;
        Person<char>s1, s2, s3;
    
        p1.a = 33;
        s1.a = 44;
    
        cout<<"p1.a = "<<p1.a << "  p2.a = "<<p2.a <<"  p3.a = "<<p3.a<<endl;
        cout<<"s1.a = "<<s1.a << "  s2.a = "<<s2.a <<"  s3.a = "<<s3.a<<endl;
        return 0;
    }
    
    
    image.png

    拷贝构造函数模板

    #include <iostream>
    #include<string>
    using namespace std; 
    
    template<class T1>
    class C2 {
        public:
        C2() {
            cout <<"这里是构造函数"<<endl;
        }
    
        template<class T2>
        C2(const C2<T2> &c2) {
            cout <<"这里是自定义的拷贝构造模板"<<endl;
        }
    
        template<class T3>
        C2<T1> & operator=(const C2<T3> &c2) {
            cout <<"这里是拷贝赋值运算符重载模板"<<endl;
            return *this;
        }
    
        int id;
    };
    
    int main() {
        C2<int> c2;
        c2.id = 123;
    
        // C2<int>c22(c2); 这里并没有调用拷贝构造
        C2<double>c22(c2);
        C2<double>c222;
        c222 =c2;
        return 0;
    }
    
    image.png

    函数模板分文件编写

    public.h

    #pragma once
    #include<iostream>
    
    using namespace std;
    
    void mySwap(int a, int b); // 普通函数
    
    template<typename T>
    void mySwap(T a, T b){// 函数模板
        cout <<"mySwap func template runs..."<<endl;
    } 
    
    template<>
    void mySwap(int a, int b);
    
    

    public.cpp

    #include "public.h"
    
    void mySwap(int a, int b) { // 普通函数
        cout <<"mySwap normal runs..."<<endl;
    }
    
    template<>
    void mySwap(int a, int b) { //具体化的函数模板
        cout <<"mySwap specific runs..."<<endl;
    }
    
    

    test.cpp

    #include <iostream>
    #include "public.h"
    
    int main() {
        mySwap(1, 1);
        mySwap('c', 'd');
        mySwap<>(1, 1);
        return 0;
    }
    
    
    image.png

    返回值类型后置

    template<typename A, typename B>
    auto add(A a, B b) -> decltype(a+b) {
        return a+b;
    }
    
    int main() {
        int a = 200;
        double b = 3.14;
        auto ret = add<int, double>(a, b);
        auto ret1 = add(a, b);
        cout << "ret = "<<ret <<"   ret1 = "<<ret1<<endl;
        return 0;
    }
    

    模板类与友元

    非模板友元

    #include <iostream>
    #include<string>
    using namespace std;
    
    template<class T1, class T2>
    class AA {
        private:
            T1 m_x;
            T2 m_y;
        public:
            AA(T1 x, T2 y):m_x(x),m_y(y) {}
            // 非模板友元,友元函数不是类模板函数,而是利用模板类参数生成的函数,只能在类内实现
            friend void show(AA<T1,T2>&aa) {
                cout <<"x = "<<aa.m_x<<"  y = "<<aa.m_y<<endl;
            }
    };
    
    int main() {
        AA<int,string>aa(23, "张三");
        show(aa);
    
        AA<char,string>bb(44, "lisi");
        show(bb);
        return 0;
    }
    

    约束模板友元(常用)

    #include <iostream>
    #include<string>
    using namespace std;
    
    // 约束模板友元:模板类实例化时候,每个实例化的类对应一个友元函数
    template<class T> //第一步:在模板类的定义前面声明友元模板
    void show(T &a);
    
    template<class T1, class T2>
    class AA {
        private:
            T1 m_x;
            T2 m_y;
        public:
            AA(T1 x, T2 y):m_x(x),m_y(y) {}
            friend void show<>(AA<T1,T2>&aa);// 第二步:在模板类中,再次声明友元函数模板
    };
    
    // 非模板友元,友元函数不是类模板函数,而是利用模板类参数生成的函数,只能在类内实现
    template<class T>
    void show(T &aa) // 第三步:友元函数模板的定义
    {
        cout <<"通用版本:x = "<<aa.m_x<<"  y = "<<aa.m_y<<endl;
    }
    
    template<>
    void show(AA<int,string>&aa) // 第三步:友元函数具体化版本
    {
        cout <<"具体化版本<int,string>  x = "<<aa.m_x<<"  y = "<<aa.m_y<<endl;
    }
    
    
    int main() {
        AA<int,string>aa(23, "张三");
        show(aa);
    
        AA<char,string>bb(44, "lisi");
        show(bb);
        return 0;
    }
    

    模板类的成员模板

    #include <iostream>
    #include<string>
    using namespace std;
    
    template<class T1, class T2>
    class AA {
        public:
            T1 m_x;
            T2 m_y;
            AA(T1 x, T2 y):m_x(x),m_y(y) {}
            void show() {cout <<"m_x = "<<m_x<<"  m_y = "<<m_y<<endl;}
    
            template<class T>
            class BB {
                public:
                    T m_a;
                    T1 m_b;
                    BB() {};
                    void show();
            };
    
            BB<string>m_bb;
    
            template<class T>
            void show(T tt);
    };
    
    template<class T1, class T2>
    template<class T>
    void AA<T1,T2>::BB<T>::show() {
        cout <<"m_a = "<<m_a<<"  m_b = "<<m_b<<endl;
    }
    
    template<class T1, class T2>
    template<class T>
    void AA<T1,T2>::show(T tt) {
        cout <<tt<<endl;
        m_bb.show();
    }
    
    int main() {
        AA<int,string>aa(23, "张三");
        aa.show();
    
        aa.m_bb.m_a = "我爱北京天安门";
        aa.m_bb.m_b = 33;
        aa.m_bb.show();
        aa.show("东风快递使命必达");
        return 0;
    }
    
    image.png

    类模板特化

    #include <iostream>
    #include<string>
    #include<map>
    using namespace std; 
    
    template<class T1, class T2>
    class C1 {
        public:
            C1() {
                cout <<"C1的构造函数C1()"<<endl;
            }
            void fun1() {
                cout <<"C1的成员函数void fun1() .."<<endl;
            }
            static int flag;
    };
    
    template<class T1, class T2>
    int C1<T1,T2>::flag = 3;
    
    // 成员变量的全特化,成员变量不支持偏特化
    template<>
    int C1<double,double>::flag = 45;
    
    // 成员函数全特化
    template<>
    void C1<int, int>::fun1() {
        cout <<"C1的成员函数void C1<int, int>::fun1()全特化"<<endl;
    }
    // 成员函数不支持偏特化
    
    // 整个类模板全特化,这里相对于泛化版来讲,哇暖是两个独立的类,除了名字一样,其他的都是不宜硬的
    // 可以有自己的成员方法和变量
    template<>
    class C1<string,string> {
        public:
            C1() {
                cout <<"C1的全特化构造函数C1()"<<endl;
            }
            void fun1() {
                cout <<"C1 全特化的成员函数void fun1() .."<<endl;
            }
            void fun2() {
                cout <<"C1 全特化的成员函数void fun2() .."<<endl;
            }
    };
    
    int main() {
        C1<int,string>c1;
        c1.fun1();
        cout << c1.flag<<endl;
        cout <<endl;
        C1<int,int>c2;
        c2.fun1();
    
        cout <<endl;
        C1<double, double>c3;
        cout << c3.flag<<endl;
    
        cout <<endl;
        C1<string,string>c4;
        c4.fun1();
        return 0;
    }
    
    image.png

    相关文章

      网友评论

          本文标题:类模板

          本文链接:https://www.haomeiwen.com/subject/fbzixdtx.html