zoukankan      html  css  js  c++  java
  • 类模板

    一、简介

    类模板和函数模板的定义及使用类似。有时,有两个或多个类,其功能是相同的,仅仅是数据类型不同。

    • 类模板用于实现类所需数据的类型参数化
    • 类模板在表示如数组、表、图等数据结构显得特别重要,这些数据结构的表示和算法不受所包含的数据类型的影响。

    二、语法

    C++ 中类模板的写法如下:

    template <类型参数表>
    class 类模板名{
      成员函数和成员变量
    };
    

    类型参数表的写法如下:

    class类塑参数1, class类型参数2, ...
    

    类模板中的成员函数放到类模板定义外面写时的语法如下:

    template <类型参数表>
    返回值类型 类模板名<类型参数名列表>::成员函数名(参数表)
    {
      ...
    }
    

    用类模板定义对象的写法如下:

    类模板名<真实类型参数表> 对象名(构造函数实际参数表);
    

    如果类模板有无参构造函数,那么也可以使用如下写法:

    类模板名 <真实类型参数表> 对象名;
    

    例:

    template<class T>
    class Person{
    public:
    	Person(T id,T age){
    		this->mAge = age;
    		this->mId = id;
    	}
    	void Show(){	
    		cout << "ID:" << mId << " Age:" << mAge << endl;
    	}
    public:
    	T mId;
    	T mAge;
    };
    void main(){	
    	//函数模板在调用的时候,可以自动类型推导
    	//类模板必须显式指定类型
    	Person<int> p(15,22);
    	p.Show();
    }
    

    三、类模板的派生

    1. 普通类派生类模板
    2. 类模板也可以派生类模板,这时,派生类模板的参数表中应包含基类模板的参数。
    3. 模板类与普通类一样也具有多继承,即模板类之间允许有多继承。

    可以从类模板派生出新的类,既可以派生类模板,也可以派生非模板类。

    //类模板派生普通类
    template<class T>
    class Person{
    public:
    	Person(){
    		mAge = 0;
    	}
    public:
    	T mAge;
    };
    //类区定义对象,这个对象需要编译分配内存,要指定类型
    class SubPerson : public Person<int>{};
    
    //类模板派生类模板
    template<class T>
    class Animal{
    public:
    	void J(){
    		cout << mAge << "动物在叫!" << endl;
    	}
    public:
    	T mAge;
    };
    
    template<class T>
    class Cat : public Animal<T>{};
    
    int main(void)
    {	
    	Cat<int> cat;//指定类型
    	return 0;
    }
    

    四、类模板外部实现成员函数

    template<class T>
    class Person{
    public:
    	Person(T age, T id);
    	void Show();
    private:
    	T mAge;
    	T mID;
    };
    //外部实现函数
    template<class T>
    Person<T>::Person(T age, T id){
    	this->mID = id;
    	this->mAge = age;
    }
    template<class T>
    void Person<T>::Show(){
    	cout << "Age:" << mAge << " ID:" << mID << endl;
    }
    

    五、类模板的编译

    首先,一个编译单元translation unit)是指一个.cpp文件以及它所#include的所有.h文件,.h文件里的代码将会被扩展到包含它的.cpp文件里,然后编译器编译该.cpp文件为一个.obj文件(假定我们的平台是win32),后者拥有PEPortable Executable,即windows可执行文件)文件格式,并且本身包含的就已经是二进制码,但是不一定能够执行,因为并不保证其中一定有main函数。当编译器将一个工程里的所有.cpp文件以分离的方式编译完毕后,再由连接器(linker)进行连接成为一个.exe文件。

    就像类一样,类模板是可以将其实现与声明放在一起的,或者也可以将接口与实现分离。但是呢,编译器由于历史原因对于分离式编译的支持非常弱,并且因平台的不同支持力度有所不同。

    STL 的类模板都是接口与实现放在一起的,随着主流走就可以。(文件保存为类模板.hpp,其实质就是将.cpp的实现代码混入.h头文件当中,定义与实现都包含在同一文件,则该类的调用者只需要include该hpp文件即可,无需再 将cpp加入到project中进行编译。)

    六、类模板中的static关键字

    不同的类型参数的类的静态成员变量是相互独立的,这是由类模板的实现机制决定的。

    #define _CRT_SECURE_NO_WARNINGS
    #include <iostream>
    using namespace std;
    
    template<class T>
    class Person{
    public:
    	static int a;
    };
    template<class T> int Person<T>::a = 0;//类外初始化
    
    int main(void)
    {
    	Person<int> p1, p2, p3;
    	Person<char> pp1, pp2, pp3;
    	p1.a = 10;
    	pp1.a = 100;
    	cout << p1.a << " " << p2.a << " " << p3.a << endl;//输出10 10 10
    	cout << pp1.a << " " << pp2.a << " " << pp3.a << endl;//输出100 100 100
    	return 0;
    }
    

    可以看到相同类型如int对应的类模板的对象之间的static成员是共享的,不同类型之间如int,float,char对应的类模板的对象之间的static是不共享的。

  • 相关阅读:
    Android App上架流程
    php字符串操作
    SpringBoot配置MongoDB多数剧源
    Spring boot使用influxDB总结
    Spring boot配置MongoDB以及Morphia踩坑记录
    使用Kubernetes的java-client实现Deployment的部署及更新操作
    Golang循环中调用go func参数异常分析
    git tag本地删除以及远程删除
    SpringBoot之GZip压缩,HTTP/2,文件上传,缓存配置
    Java服务使用Redis实现分布式全局唯一标识
  • 原文地址:https://www.cnblogs.com/gqw-myblogs/p/14238561.html
Copyright © 2011-2022 走看看