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;
- }
-