类模板

2022-11-28  本文已影响0人  arkliu

类模板的基本语法

#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
上一篇下一篇

猜你喜欢

热点阅读