C++模板:函数模板、类模板、模板与继承

时间:2021-06-22 19:03:17

  C++模板:描述    

        C++提供一种模板的机制来减少代码重复。比如:对于同一样函数使用不同的数据类型,int,double,char等。C++模板属于“元编程”的范畴。

C++ 模板函数

                 1.支持不同数据类型的函数重载:

#include <iostream>
using namespace std;

int square (int x)
{
return x * x;
};

float square (float x)
{
return x * x;
};

double square (double x)
{
return x * x;
};

main()
{
int i, ii;
float x, xx;
double y, yy;

i = 2;
x = 2.2;
y = 2.2;

ii = square(i);
cout << i << ": " << ii << endl;

xx = square(x);
cout << x << ": " << xx << endl;

yy = square(y);
cout << y << ": " << yy << endl;
}


2.支持所有数据类型的函数模板

#include <iostream>
using namespace std;

template <class T>
inline T square(T x)
{
T result;
result = x * x;
return result;
};



main()
{
int i, ii;
float x, xx;
double y, yy;

i = 2;
x = 2.2;
y = 2.2;

ii = square<int>(i);
cout << i << ": " << ii << endl;

xx = square<float>(x);
cout << x << ": " << xx << endl;

// Explicit use of template
yy = square<double>(y);// 显式使用模板
cout << y << ": " << yy << endl;

yy = square(y);//隐含的方式使用模板
cout << y << ": " << yy << endl;
}

注明:模板的关键字可以用class或者typename.

  • template<class T>
  • template<typename T>

两者表达的意思是一样的,但是我更喜欢使用后者。

  • 可以采用两种方式使用模板函数square<int>(value) or square(value).
  • 在模板函数的定义中,T代表数据类型。
  • 模板的声明和定义必须在同一个文件中,如头文件中。
  • C语言的宏定义也可以实现函数模板的功能,#define square(x) (x * x)
    但是宏没有类型检查,函数模板有类型检查。

     

    C++ 模板特例化

  • 下面的例子字符串类型需要特殊处理,采用模板的特例化

  • #include <iostream>
    using namespace std;

    template <class T>
    inline T square(T x)
    {
    T result;
    result = x * x;
    return result;
    };

    // 模板特殊化
    template <>
    string square<string>(string ss)
    {
    return (ss+ss);
    };

    main()
    {
    int i = 2, ii;
    string ww("Aaa");

    ii = square<int>(i);
    cout << i << ": " << ii << endl;

    cout << square<string>(ww) << endl;
    }

    注明:模板特例化用于当一个数据类型需要进行不同的处理和实现的情况。



  •  C++ 模板无类型参数

  •  

    #include <iostream>
    using namespace std;

    template <typename T, int count>
    void loopIt(T x)
    {
    T val[count];

    for(int ii=0; ii<count; ii++)
    {
    val[ii] = x++;
    cout << val[ii] << endl;
    }
    };

    main()
    {
    float xx = 2.1;

    loopIt<float,3>(xx);
    }

     C++ 模板默认类型参数以及无类型参数

    #include <iostream>
    using namespace std;

    template <typename T=float, int count=3>
    T multIt(T x)
    {
    for(int ii=0; ii<count; ii++)
    {
    x = x * x;
    }
    return x;
    };

    main()
    {
    float xx = 2.1;

    cout << xx << ": " << multIt<>(xx) << endl;;
    }


    注明:multIt<>没有指定参数类型,默认为float;

     C++ 类模板

    类模板定义:template <class T> class MyTemplateClass { ... };

    类模板特例化:template <> class MyTemplateClass <specific-data-type> { ... };

    File: Matrix2x2.hpp

    #ifndef MATRIX_2X2_HPP__
    #define MATRIX_2X2_HPP__

    using namespace std;

    /**
    m(11) m(12)
    m(21) m(22)
    */

    template <class T>
    class Matrix2x2
    {
    public:
    Matrix2x2(T m11, T m12, T m21, T m22); //constructor
    Matrix2x2(T m[2][2]);
    Matrix2x2();

    int Add(Matrix2x2 x)
    int Multiply(Matrix2x2 x)
    void Print();
    T m[2][2];
    };

    template <class T>
    Matrix2x2<T>::Matrix2x2(T _m11, T _m12, T _m21, T _m22)
    {
    m[0][0] = _m11;
    m[0][1] = _m12;
    m[1][0] = _m21;
    m[1][1] = _m22;
    }

    template <class T>
    Matrix2x2<T>::Matrix2x2(T _m)
    {
    m[0][0] = _m[0][0];
    m[0][1] = _m[0][1];
    m[1][0] = _m[1][0];
    m[1][1] = _m[1][1];
    }

    template <class T>
    Matrix2x2<T>::Matrix2x2()
    {
    m[0][0] = 0;
    m[0][1] = 0;
    m[1][0] = 0;
    m[1][1] = 0;
    }

    template <class T>
    Matrix2x2<T>::Add(Matrix2x2 _x)
    {
    Matrix2x2<T> sum;
    sum.m[0][0] = m[0][0] + _x.m[0][0];
    sum.m[0][1] = m[0][1] + _x.m[0][1];
    sum.m[1][0] = m[1][0] + _x.m[1][0];
    sum.m[1][1] = m[1][1] + _x.m[1][1];
    return sum;
    }

    template <class T>
    Matrix2x2<T>::Multiply(Matrix2x2 _x)
    {
    Matrix2x2<T> sum;
    sum.m[0][0] = m[0][0] * _x.m[0][0] + m[0][1] * _x.m[1][0];
    sum.m[0][1] = m[0][0] * _x.m[0][1] + m[0][1] * _x.m[1][1];
    sum.m[1][0] = m[1][0] * _x.m[0][0] + m[1][1] * _x.m[1][0];
    sum.m[1][1] = m[1][0] * _x.m[0][1] + m[1][1] * _x.m[1][1];
    return sum;
    }

    template <class T>
    Matrix2x2<T>::Print()
    {
    cout << "|" << m[0][0] << " " << m[0][1] << "|" << endl;
    cout << "|" << m[1][0] << " " << m[1][1] << "|" << endl;
    }

    #endif


    TestMatrix2x2.cpp

    #include <iostream>

    #include "Matrix2x2.hpp"

    using namespace std;

    int main(int argc, char* argv[])
    {
    Matrix2x2<int> X(1,2,3,4);
    Matrix2x2<int> Y(5,6,7,8);

    cout << "X:" << endl;
    X.Print();

    cout << "Y:" << endl;
    Y.Print();

    Matrix2x2<int> A = X.Add(Y);
    cout << "A:" << endl;
    A.Print();

    Matrix2x2<int> B = X.Add(Y);
    cout << "B:" << endl;
    B.Print();
    }


     

     C++ 普通类和类模板的静态成员变量

    普通类的静态成员函数:

    #include <iostream>

    using namespace std;


    class XYZ
    {
    public:
    void putPri();
    static int ipub;
    private:
    static int ipri;
    };


    void XYZ::putPri()
    {
    cout << ipri++ << endl;
    }

    // 静态成员变量初始化:
    int XYZ::ipub = 1;
    int XYZ::ipri = 1;

    main()
    {
    XYZ aaa;
    XYZ bbb;

    aaa.putPri();
    cout << aaa.ipub << endl;
    bbb.putPri();
    }

    类模板的静态成员:

    #include <iostream>

    using namespace std;

    template <class T>
    class XYZ
    {
    public:
    void putPri();
    static T ipub;
    private:
    static T ipri;
    };

    template <class T>
    void XYZ<T>::putPri()
    {
    cout << ipri++ << endl;
    }

    // 静态成员初始化:
    template <class T> T XYZ<T>::ipub = 1;
    template <class T> T XYZ<T>::ipri = 1.2;

    main()
    {
    XYZ<int> aaa;
    XYZ<float> bbb;

    aaa.putPri();
    cout << aaa.ipub << endl;
    bbb.putPri();
    }

     C++ 模板的模板参数

    #include <iostream>
    using namespace std;

    template <template <typename T> typename U>
    class Xyz
    {
    ....
    };

     C++ 类模板和继承

    Color.hpp (无模板的基类)

    #ifndef COLOR_HPP__
    #define COLOR_HPP__
    #include <string>
    enum eColor { none = 0, red, white, blue, yellow, green, black };

    class Color
    {
    public:
    Color(eColor color);
    void setColor(eColor color);
    eColor getColor() { return mColor; };
    std::string getStrColor();

    protected:
    eColor mColor;
    };

    Color::Color(eColor _color)
    {
    mColor = _color;
    }

    void Color::setColor(eColor _color)
    {
    mColor = _color;
    }

    std::string Color::getStrColor()
    {
    switch(mColor)
    {
    case red:
    return "red";
    case white:
    return "white";
    case blue:
    return "blue";
    case yellow:
    return "yellow";
    case green:
    return "green";
    case black:
    return "black";
    case none:
    default:
    return "none";
    }
    }
    #endif


    File: Circle.hpp (模板基类)

    #ifndef CIRCLE_HPP__
    #define CIRCLE_HPP__
    #include <math.h>
    #include <string>

    #include "Color.hpp"

    template <typename T>
    class Circle : public Color
    {
    public:
    Circle(T centerX, T centerY, T radius, eColor color);
    Circle(T centerX, T centerY, T radius);
    Circle(T radius);

    T area();
    T circumference();
    T getX();
    T getY();
    T getRadius();

    protected:
    T x;
    T y;
    T radius;
    };

    template <typename T>
    Circle<T>::Circle(T _x, T _y, T _radius, eColor _color)
    : Color(_color)
    {
    x = _x;
    y = _y;
    radius = _radius;
    }

    template <typename T>
    Circle<T>::Circle(T _x, T _y, T _radius)
    : Color(none)
    {
    x = _x;
    y = _y;
    radius = _radius;
    }

    template <typename T>
    Circle<T>::Circle(T _radius)
    : Color(none)
    {
    x = const_cast<T>(0);
    y = const_cast<T>(0);
    radius = _radius;
    }

    template <typename T>
    T Circle<T>::area()
    {
    return M_PI * radius * radius;
    }

    template <typename T>
    T Circle<T>::circumference()
    {
    return const_cast<T>(2) * M_PI * radius;
    }
    #endif


    File: testCircle.cpp

     

    #include <iostream>
    #include "Circle.hpp"

    using namespace std;

    int main(int argc, char* argv[])
    {
    Circle<float> circleA(0.0, 0.0, 10.0, white);
    cout << "Area: " << circleA.area() << endl;
    cout << "Color: " << circleA.getStrColor() << endl;
    }


     

     一个模板类继承另外一个模板类:

    File: Sphere.hpp (派生类)

    #ifndef SPHERE_HPP__
    #define SPHERE_HPP__

    #include "Circle.hpp"

    template <typename T>
    class Sphere : public Circle<T>
    {
    public:
    Sphere(T centerZ, T centerX, T centerY, T radius, eColor color);
    Sphere(T radius);
    Sphere();

    T surfaceArea();
    T volume();
    T getZ();

    private:
    T z;
    };

    template <typename T>
    Sphere<T>::Sphere(T _x, T _y, T _z, T _radius, eColor _color)
    : Circle<T>::Circle (_x, _y, _radius, _color)
    {
    this->z = _z;
    }

    template <typename T>
    Sphere<T>::Sphere(T _radius)
    : Circle<T>::Circle (_radius)
    {
    this->x = const_cast<T>(0);
    this->y = const_cast<T>(0);
    this->z = const_cast<T>(0);
    this->radius = _radius;
    }

    template <typename T>
    Sphere<T>::Sphere()
    {
    this->x = const_cast<T>(0);
    this->y = const_cast<T>(0);
    this->z = const_cast<T>(0);
    this->radius = const_cast<T>(1);
    }

    template <typename T>
    T Sphere<T>::surfaceArea()
    {
    return const_cast<T>(4) * M_PI * this->radius * this->radius;
    }

    template <typename T>
    T Sphere<T>::volume()
    {
    T three = 3;
    T four = 4;
    return four * M_PI * this->radius * this->radius * this->radius / three;
    }
    #endif


    注明:用this来显示类的依赖

    File: testSphere.cpp

    #include <iostream>
    #include "Sphere.hpp"

    using namespace std;

    int main(int argc, char* argv[])
    {
    Sphere<float> sphereA(0.0, 0.0, 0.0,10.0, blue);
    cout << "Volume: " << sphereA.volume() << endl;
    cout << "Color: " << sphereA.getStrColor() << endl;
    }