C++模板:函数模板、类模板、模板与继承 - 小众知识

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

2013年01月27日 14:18:05 苏内容
  标签: 模板/继承/C++
阅读:7328

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(); 

类模板的静态成员:

[cpp] view plaincopy
#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++ 模板的模板参数
[cpp] view plaincopy
#include <iostream> 
using namespace std; 
 
template <template <typename T> typename U> 
class Xyz 

    .... 
}; 
 C++ 类模板和继承
Color.hpp (无模板的基类)

[cpp] view plaincopy
#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 (模板基类)

[cpp] view plaincopy
#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

 

[cpp] view plaincopy
#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 (派生类)

[cpp] view plaincopy
#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
[cpp] view plaincopy
#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; 

扩展阅读