C/C++程序设计专题散文摄影

C++系列 --- 类模板概念,类模板定义和使用

2019-05-04  本文已影响209人  307656af5a04

今天呢,我们一起来学习下模板与泛型中的知识点,类模板的概念,类模板的定义与使用,希望大家通过本节的学习,可以对类模板有一个清晰的理解!

1、概述

用类模板来实例化一个特定的类;

编译器不能为类模板推断模板参数类型,所以为了使用类模板,我们必须在模板名后面用<>来提供额外的信息,这些信息其实就是对应着模板类参数列表里面的参数;

类模板实现同一套代码,可以应付不同的数据类型,这样就显得精简多了。

2、类模板定义

template<typename 形参名1,typename 形参名2,......typename 形参名n>
class 类名
{

};

实例
myvector类模板 模仿vector

实例化类模板的时候,必须有类的全部信息,包括类模板中成员函数的函数体;

myvector.h文件

#ifndef __MYVECTOR__
#define __MYVECTOR__

// 定义类模板
// 名字为T的模板参数,
// 用来表示myvector这个容器
// 所保存的元素类型
template<typename T>  
class myvector
{
public:
    // 迭代器 vector iterator
    typedef T* myiterator;  

public:
    // 构造函数
    myvector(); 

    // 赋值运算符重载,在类模板内部使用模板名,
    // 并不需要提供模板参数
    myvector& operator=(const myvector&);  
    //myvector<T>& operator=(const myvector<T>&);

public:
    // 迭代器的起始位置
    myiterator mybegin();  
    // 迭代器的最后一个元素的下一个位置
    myiterator myend(); 

    //类模板的成员函数
public:
    // 把函数的函数体(函数具体实现)
    // 放在类模板的定义中
    //void myfunc() {}; 

    void myfunc();
};

// 类模板函数在类外部实现
template<typename T>
void myvector<T>::myfunc()
{
    // ......
    return;
}

// 重载赋值运算符,<T>表示
// 返回的是一个实例化了的myvector
template<typename T>
myvector<T>& myvector<T>::operator=(const myvector&)
{
    return *this;
}

#endif

main.cpp文件

#include <iostream>
#include "myvector.h"

using namespace std;

int main(int argc, char** argv)
{
    // 这个时候,编译器给生成一个具体的类
    myvector<int> tmpvec1;  
    myvector<double> tmpvec2;
    myvector<string> tmpvec2;
}

myvector是类模板名,它不是一个类名,类模板是用来实例化类类型的;所以myvector<int>,myvector<double>才是类型名(实例化的类型);所以,一个实例化的类型,总会用尖括号<>包含着模板参数。

3、类模板的成员函数

类模板成员函数,可以写在类模板定义中,这种写在类模板定义中的函数会被隐式的声明为inline函数;

类模板被实例化之后,模板的每个实例都会有自己版本的成员函数,所以,类模板的成员函数具有和这个类模板相同的模板参数;

如果你把类模板成员函数的定义写在类模板的外边,那么这个成员函数的模板参数就必须体现出来;

定义在类模板之外的成员函数必须以关键字template开头,后面接类模板参数列表,同时,在类名后面要用尖括号<>把模板参数列表里面的所有模板参数名列出来,如果是多个模板参数,用逗号分隔;

类外实现成员函数的定义

// 类模板函数在类外部实现
template<typename T>
void myvector<T>::myfunc()
{
    // ......
    return;
}

一个类模板虽然肯能有很多的成员函数,但是,当你实例化模板之后,如果你后续没有使用到某个函数,则这个成员函数不会被实例化,说白了,就是一个实例化的模板,它的成员函数只有在使用的时候才被实例化。

4、模板类名字的使用

// 类模板名字的使用,即T的使用
// 重载赋值运算符,<T>表示
// 返回的是一个实例化了的myvector
template<typename T>
myvector<T>& myvector<T>::operator=(const myvector&)
{
    return *this;
}

5、非类型模板参数

实例:
myarray.h文件

#ifndef __MYARRAY__
#define __MYARRAY__

template<typename T,int size = 10>
class myarray
{

private:
    T arr[size];

public:
    void myfunc();

};
template<typename T, int size>
void myarray<T,size>::myfunc()
{
    cout << size << endl;
    return;
}
#endif

int size = 10,即为非类型模板参数

main.cpp文件

#include <iostream>
#include "myarray.h"

using namespace std;

int main(int argc, char** argv)
{
    myarray<int, 100> tmparray1;
    tmparray1.myfunc();  // 100

    myarray<int> tmparray2;
    tmparray2.myfunc(); //10

    system("pause");
    return 0;
}

实验结果

实验结果

非类型模板参数的一些限制:
(1)浮点型不能左非类型模板参数,比如float,double
(2)类类型一般也不允许左非类型模板参数

好了,今天的C++模板与泛型学到这里就结束了,希望大家可以认真理解哦!!

我是奕双,现在已经毕业将近两年了,从大学开始学编程,期间学习了C需要编程,C++需要编程,Win32编程,MFC编程,毕业之后进入一家图像处理相关领域的公司,掌握了用OpenCV对图像进行处理,如果大家对相关领域感兴趣的话,可以关注我,我这边会为大家进行解答哦!如果大家需要相关学习资料的话,可以私聊我哦!

上一篇下一篇

猜你喜欢

热点阅读