zoukankan      html  css  js  c++  java
  • C++学习34 模板类

    C++除了支持模板函数,还支持模板类。模板类的目的同样是将数据类型参数化。

    声明模板类的语法为:

    template<typename 数据类型参数 , typename 数据类型参数 , …> class 类名{
        //TODO:
    };

    模板类和模板函数都是以 template 开头,后跟数据类型参数列表;数据类型参数不能为空,多个参数用逗号隔开。

    一但声明了模板类,就可以用数据类型参数来声明类中的成员变量和成员函数。也就是说,原来使用C++内置类型(比如 int、float、char 等)的地方,都可以用类型参数来代替。

    假如我们现在要定义一个类来表示坐标,要求坐标的数据类型可以是整数、小数和字符串,例如:

    x = 10、y = 10
    x = 12.88、y = 129.65
    x = "东京180度"、y = "北纬210度"

    这个时候就可以使用模板类,请看下面的代码:

    template<typename T1, typename T2>  //这里不能有分号
    class Point{
    private:
        T1 x;
        T2 y;
    public:
        Point(T1 _x, T2 _y): x(_x),y(_y){}
        T1 getX();
        void setX(T1 x);
        T2 getY();
        void setY(T2 y);
    };

    坐标 x 和 y 的数据类型不确定,借助模板类,就可以将数据类型参数化,否则就要定义多个类。

    注意:模板头和类头是一个整体,可以换行,但是中间不能有分号。

    上面是类的声明,还需要在类外定义成员函数。在类外定义成员函数时仍然需要带上模板头,语法为:

    template<类型参数列表> 函数返回值类型 类名<类型参数列表>::函数名(参数列表){
        //TODO:
    }

    下面对 Point 类的成员函数进行定义:

    template<typename T1, typename T2>
    T1 Point<T1, T2>::getX(){
        return x;
    }
    template<typename T1, typename T2>
    void Point<T1, T2>::setX(T1 x){
        this->x = x;
    }
    template<typename T1, typename T2>
    T2 Point<T1, T2>::getY(){
        return y;
    }
    template<typename T1, typename T2>
    void Point<T1, T2>::setY(T2 y){
        this->y = y;
    }

    应当注意:在类外定义成员函数时,template 后面的类型参数列表要与类声明时的一致。

    模板类的实例化

    实例化模板类时,需要指明数据类型。例如:

    Point<int, int> p1(10, 20);
    Point<int, float> p2(10, 15.5);
    Point<float, char*> p3(12.4, "东京180度");

    与模板函数不同的是,模板类在实例化时必须显式地指明数据类型,编译器不能根据给定的数据推演出数据类型。下面的实例化代码是错误的:

    Point p1(10, 20);
    Point p2(10.4, "东京180度");

    至此,我们就可以定义模板类并实例化了。

    将上面的代码整合起来,给出一个完整的示例:

    #include <iostream>
    using namespace std;
    template<typename T1, typename T2>  //这里不能有分号
    class Point{
    private:
        T1 x;
        T2 y;
    public:
        Point(T1 _x, T2 _y): x(_x),y(_y){}
        T1 getX();
        void setX(T1 x);
        T2 getY();
        void setY(T2 y);
    };
    template<typename T1, typename T2>
    T1 Point<T1, T2>::getX(){
        return x;
    }
    template<typename T1, typename T2>
    void Point<T1, T2>::setX(T1 x){
        this->x = x;
    }
    template<typename T1, typename T2>
    T2 Point<T1, T2>::getY(){
        return y;
    }
    template<typename T1, typename T2>
    void Point<T1, T2>::setY(T2 y){
        this->y = y;
    }
    int main(){
        Point<int, int> p1(10, 20);
        cout<<"p1.x="<<p1.getX()<<", p1.y="<<p1.getY()<<endl;
       
        Point<int, char*> p2(10, "东京180度");
        cout<<"p2.x="<<p2.getX()<<", p2.y="<<p2.getY()<<endl;
       
        Point<float, float> *p = new Point<float, float>(10.6, 109.3);
        cout<<"p->x="<<p->getX()<<", p->y="<<p->getY()<<endl;
        return 0;
    }

    注意代码第 44 行,当定义模板类的指针时,赋值号两边都需要指明具体的数据类型,且要保持一致。下面的写法是错误的:

    //赋值号两边的数据类型不一致
    Point<float, float> *p = new Point<float, int>(10.6, 109);
    //赋值号右边没有指明数据类型
    Point<float, float> *p = new Point(10.6, 109);
  • 相关阅读:
    dotnetcharting 生成柱状图,饼图等统计图
    asp.net 前后台相互调用
    SQL基础和高级(语法格式)总结二
    自己动手JQuery插件开发
    SQL基础之创建数据库,表,架构
    SQL基础和高级(语法格式)总结一
    ado.net总结
    [Nescafé 26] 小猫爬山&&售货员的难题&&区间众数(随机化大法好)
    POJ2774 后缀自动机&后缀数组
    【方向学习】单片机
  • 原文地址:https://www.cnblogs.com/Caden-liu8888/p/5836670.html
Copyright © 2011-2022 走看看