C++模板:函数模板、类模板、模板与继承
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;
类模板定义: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();}
普通类的静态成员函数:
#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;}