• 类模板


    1.7 类模板

    1.7.1 类模板基本概念

    类模板和函数模板的定义和使用类似,我们已经进行了介绍。有时,有两个或多个类,其功能是相同的,仅仅是数据类型不同。

    l  类模板用于实现类所需数据的类型参数化

    template<class NameType, class AgeType>
    class Person
    {
    public:
        Person(NameType name, AgeType age)
        {
            this->mName = name;
            this->mAge = age;
        }
        void showPerson()
        {
            cout << "name: " << this->mName << " age: " << this->mAge << endl;
        }
    public:
        NameType mName;
        AgeType mAge;
    };
    
    void test01()
    {
        //Person P1("德玛西亚",18); // 类模板不能进行类型自动推导 
        Person<string, int>P1("德玛西亚", 18);
        P1.showPerson();
    }

    1.7.2 类模板做函数参数

    #include "stdafx.h"
    #include <iostream>
    using namespace std;
    #include <string>
    
    template <class NameType,class AgeType>
    class Person
    {
    public:
        Person(NameType name, AgeType age)
        {
            this->m_Name = name;
            this->m_Age = age;
        }
        void PrintPerson()
        {
            cout << "Name:" << this->m_Name << " Age:" << this->m_Age << endl;
        }
    
        NameType m_Name;
        AgeType m_Age;
    };
    
    void DoBussiness(Person<string, int>& p)
    {
        p.m_Age += 20;
        p.m_Name += "_VIP";
        p.PrintPerson();
    }
    
    //2.参数模板化
    template<class T1,class T2>
    void doWork(Person<T1, T2>&p)
    {
        cout << typeid(T1).name() << endl;
        cout << typeid(T2).name() << endl;
        p.PrintPerson();
    }
    
    //3.整体类型化
    template<class T>
    void doWork3(T& p)
    {
        cout << typeid(T).name() << endl;
        p.PrintPerson();
    }
    
    int main()
    {
        Person<string,int> p("sunwukong", 100);
        //p.PrintPerson();
        DoBussiness(p);
        doWork(p);
        doWork3(p);
        return 0;
    }

    1.7.3 类模板派生普通类

    //类模板
    template<class T>
    class MyClass{
    public:
        MyClass(T property){
            this->mProperty = property;
        }
    public:
        T mProperty;
    };
    
    //子类实例化的时候需要具体化的父类,子类需要知道父类的具体类型是什么样的
    //这样c++编译器才能知道给子类分配多少内存
    
    //普通派生类
    class SubClass : public MyClass<int>{
    public:
        SubClass(int b) : MyClass<int>(20){
            this->mB = b;
        }
    public:
        int mB;
    };
    #include <iostream>
    using namespace std;
    #include <string>
    
    template<class T>
    class Base
    {
    public:
        T m_A;
    };
    
    class Child :public Base<int>
    {
        
    };
    
    template <class T1,class T2>
    class Child2 :public Base<T1>
    {
    public:
        T1 m_B;
    };
    
    int main()
    {
        Child2<int, double> c2;
        return 0;
    }

    1.7.5 类模板类内实现

    template<class NameType, class AgeType>
    class Person
    {
    public:
        Person(NameType name, AgeType age)
        {
            this->mName = name;
            this->mAge = age;
        }
        void showPerson()
        {
            cout << "name: " << this->mName << " age: " << this->mAge << endl;
        }
    public:
        NameType mName;
        AgeType mAge;
    };
    
    void test01()
    {
        //Person P1("德玛西亚",18); // 类模板不能进行类型自动推导 
        Person<string, int>P1("德玛西亚", 18);
        P1.showPerson();
    }

    1.7.6 类模板类外实现

    class Person{
    public:
        Person(T1 name, T2 age);
        void showPerson();
    
    public:
        T1 mName;
        T2 mAge;
    };
    
    
    //类外实现
    template<class T1, class T2>
    Person<T1, T2>::Person(T1 name, T2 age){
        this->mName = name;
        this->mAge = age;
    }
    
    
    template<class T1, class T2>
    void Person<T1, T2>::showPerson(){
        cout << "Name:" << this->mName << " Age:" << this->mAge << endl;
    }
    
    void test()
    {
        Person<string, int> p("Obama", 20);
        p.showPerson();
    }
    
    int main(){
    
        test();
    
        system("pause");
        return EXIT_SUCCESS;
    }

    1.7.7 类模板头文件和源文件分离问题

    Person.hpp

    #pragma once
    #include <iostream>
    using namespace std;
    
    template<class T1,class T2>
    class Person
    {
    public:
        Person(T1 t1, T2 t2);
        ~Person();
        void PrintInfo()
        {
            cout << "------------void PrintInfo()--------------" << endl;
            cout << "m_a: " << m_a  << " "<< typeid(T1).name() << endl;
            cout << "m_b: " << m_b  << " " <<typeid(T2).name() << endl;
            cout << "------------------------------------------" << endl;
        }
        void showInfo();
        T1 m_a;
        T2 m_b;
    };
    
    template<class T1,class T2,class T3>
    class xiaoming :public Person<T1, T2>
    {
    public:
        xiaoming(T1 a, T2 b, T3 c);
        ~xiaoming();
        void showInfo();
        T3 m_c;
    };
    
    template<class T1, class T2>
    Person<T1, T2>::Person(T1 t1, T2 t2)
        :m_a(t1)
        , m_b(t2)
    {
    }
    
    
    template<class T1, class T2>
    Person<T1, T2>::~Person()
    {
    }
    
    template<class T1, class T2>
    void Person<T1, T2>::showInfo()
    {
        cout << "---------------void Person<T1,T2>::showInfo()---------------" << endl;
        cout << "m_a: " << m_a << " " << "m_b: " << m_b << " " << endl;
        cout << "--------------------------------------------------------------" << endl;
    }
    
    template<class T1, class T2, class T3>
    xiaoming<T1, T2, T3>::xiaoming(T1 a, T2 b, T3 c)
        :Person(a, b)
        , m_c(c)
    {
    }
    
    template<class T1, class T2, class T3>
    xiaoming<T1, T2, T3>::~xiaoming()
    {
    
    }
    
    template<class T1, class T2, class T3>
    void xiaoming<T1, T2, T3>::showInfo()
    {
        cout << "---------void xiaoming<T1, T2, T3>::showInfo()----------" << endl;
        cout << "m_a: " << m_a << " " << typeid(T1).name() << endl;
        cout << "m_b: " << m_b << " " << typeid(T2).name() << endl;
        cout << "m_c: " << m_c << " " << typeid(T3).name() << endl;
        cout << "--------------------------------------------------------" << endl;
    }

    调用

    #include "stdafx.h"
    #include <iostream>
    using namespace std;
    #include <string>
    //#include "Person.h"
    #include "Person.hpp"
    
    int main()
    {
        //Child2<int, double> c2;
        Person<int, string> p1(10,"test p1");
        p1.showInfo();
        p1.PrintInfo();
    
        xiaoming<int, string, int> p2(10, "xiaoming", 1000);
        p2.showInfo();
        p2.PrintInfo();
        return 0;
    }

    结论: 案例代码在qt编译器顺利通过编译并执行,但是在Linux和vs编辑器下如果只包含头文件,那么会报错链接错误,需要包含cpp文件,但是如果类模板中有友元类,那么编译失败!

    解决方案: 类模板的声明和实现放到一个文件中,我们把这个文件命名为.hpp(这个是个约定的规则,并不是标准,必须这么写).

    原因:

    类模板需要二次编译,在出现模板的地方编译一次,在调用模板的地方再次编译。

    C++编译规则为独立编译。

    1.7.8     模板类碰到友元函数

    // Template02.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    
    #include <iostream>
    using namespace std;
    #include <string>
    
    //2.2 外部实现1 前置声明
    template<class T1, class T2> class Person;
    //2.3 外部实现1 外部声明友元
    template<class T1, class T2> void PrintPerson2(Person<T1, T2>& p);
    
    template<class T1,class T2>
    class Person
    {
        //3 外部实现2
        template<class U1, class U2>
        friend void PrintPerson3(Person<U1, U2>& p);
    
        //2.1外部实现1
        friend void PrintPerson2<>(Person<T1, T2>& p);
    
        //1.内部实现
        friend void PrintPerson(Person<T1, T2>& p) {
            cout << "Name:" << p.m_Name << " Age:" << p.m_Age << endl;;
        }
    
        
    
    public:
        Person(T1 name, T2 age)
        {
            this->m_Name = name;
            this->m_Age = age;
        }
    
        void showPerson()
        {
            cout << "Name:" << this->m_Name << " Age:" << this->m_Age << endl;
        }
    private:
        T1 m_Name;
        T2 m_Age;
    };
    
    template<class T1,class T2>
    void PrintPerson2(Person<T1, T2>& p)
    {
        cout << "Name:" << p.m_Name << " Age:" << p.m_Age << endl;
    }
    
    
    template<class U1, class U2>
    void PrintPerson3(Person<U1, U2>& p)
    {
        cout << "Name:" << p.m_Name << " Age:" << p.m_Age << endl;
    }
    int main()
    {
        Person<string, int> p("sunwukong", 20);
        //p1.showPerson();
        //PrintPerson2(p);
        PrintPerson3(p);
        return 0;
    }
  • 相关阅读:
    BroadcastReceiver 小结
    Android Manifest.xml 之 Intent-filter
    First Phone Interview
    XDK html development --- Cross Domain Request
    Github Git usage
    为节省内存,动态添加view布局和控件
    相似的概念
    让一个view 获得焦点
    ListView 关于减少耗时方法调用优化
    SearchView 分解设置属性
  • 原文地址:https://www.cnblogs.com/mmc9527/p/10453321.html
Copyright © 2020-2023  润新知