模板构造函数不同于模板类
使用模板的作用有以下两个好处:
1.可以将类型作为参数传进;
2.可以传进不同类型的参数;
下面先看看模板类
模板类
模板类的两个示例:
template <class T> //声明一个模板,虚拟类型名为T。注意:这里没有分号。
class Compare //类模板名为Compare
{
public :
Compare(T a,T b)
{
x=a;y=b;
}
T max( )
{
return (x>y)?x:y;
}
T min( )
{
return (x<y)?x:y;
}
private :
T x,y;
};
声明了模板类型T之后,该类型可以用在构造函数、成员函数、成员变量等各个地方。
下面看另外一个例子。
template<typename _Tp, int chs> class Mat_ {
public:
typedef _Tp value_type;
// default constructor
Mat_() : rows(0), cols(0), channels(0), data(NULL), step(0), allocated(false), datastart(NULL), dataend(NULL) {
}
// constructs 2D matrix of the specified size
Mat_(int _rows, int _cols);
// constucts 2D matrix and fills it with the specified value _s
Mat_(int _rows, int _cols, const Scalar& _s);
// constructor for matrix headers pointing to user-allocated data, no data is copied
Mat_(int _rows, int _cols, void* _data);
// copy constructor, NOTE: deep copy
Mat_(const Mat_<_Tp, chs>& _m);
Mat_& operator = (const Mat_& _m);
// reports whether the matrix is continuous or not
bool isContinuous() const;
// returns true if the matrix is a submatrix of another matrix
bool isSubmatrix() const;
// copies the matrix content to "_m"
void copyTo(Mat_<_Tp, chs>& _m, const Rect& rect = Rect(0, 0, 0, 0)) const;
// return typed pointer to the specified matrix row,i0, A 0-based row index
const uchar* ptr(int i0 = 0) const;
uchar* ptr(int i0 = 0);
// no data is copied, no memory is allocated
void getROI(Mat_<_Tp, chs>& _m, const Rect& rect = Rect(0, 0, 0, 0));
// Locates the matrix header within a parent matrix
void locateROI(Size& wholeSize, Point& ofs) const;
// Adjusts a submatrix size and position within the parent matrix
void adjustROI(int dtop, int dbottom, int dleft, int dright);
// value converted to the actual array type
void setTo(const Scalar& _value);
// Converts an array to another data type with optional scaling
// the method converts source pixel values to the target data type
// if it does not have a proper size before the operation, it is reallocated
// \f[m(x,y) = saturate \_ cast<rType>( \alpha (*this)(x,y) + \beta )\f]
template<typename _Tp2>
void convertTo(Mat_<_Tp2, chs>& _m, double alpha = 1, const Scalar& scalar = Scalar(0, 0, 0, 0)) const;
Mat_<_Tp, chs>& zeros(int _rows, int _cols);
// returns the matrix cols and rows
Size size() const;
// returns true if Mat_::total() is 0 or if Mat_::data is NULL
bool empty() const;
// returns the matrix element size in bytes: sizeof(_Tp) * channels
size_t elemSize() const;
// returns the size of each matrix element channel in bytes: sizeof(_Tp)
size_t elemSize1() const;
// returns the total number of array elements
size_t total() const;
// release memory
inline void release();
// destructor - calls release()
~Mat_() {
release(); };
public:
// the number of rows and columns
int rows, cols;
// channel num
int channels;
// pointer to the data
uchar* data;
// bytes per row
int step; // stride
// memory allocation flag
bool allocated;
// helper fields used in locateROI and adjustROI
const uchar* datastart;
const uchar* dataend;
}; // Mat_
对于模板类而言,在使用的时候必须指定加上类型,比如说:
const Mat_<uchar, 1>& mask = Mat_<uchar, 1>()
模板类的话就是在构造对象的时候要加上类型,该类型可以广泛应用于该类的内部,同时由以上可以看出,template表明的模板的意思,关于类型既可以用typename关键字指定,也可以用class.
同时, 一个类模板可以作为基类,派生出派生模板类。
如下面的例子所示:
template<typename _Tp, int chs>
static int resize_cubic(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst)
这里是派生出来的模板函数。
但是,区别在于!
模板类必须显示的调用,但是函数模板既可以显示调用,也可以隐式调用。
非模板类的模板构造函数
非模板类的模板构造函数的目的同模板类一样,也是为了传入类型参数(T)或者非固定类型的参数(T a,T b,…)。它属于成员模板。同样是要在构造的时候传入类型,编译器需要区别模板构造函数和模板类。
当然,网上有些人说构造函数是成员,并且不允许明确地使它们成为模板。
首先,模板构造函数必须将类型参数做输入,不然有可能和默认构造函数混淆,编译无法通过;
比如,以下是不可以的:
class any{
template <typename ValueType> any();
};
但是如果这样是可以的;
class any{
template <typename ValueType> any(ValueType a);
};
或者不传实参只传类型,这样写也可以:
class any{
template <typename ValueType> any(const ValueType &);
};
下面来看一个问题,当构造函数有以下两种时:
any(const any &);
template <typename ValueType>
any(const ValueType &);
编译器将选择非模板化版本,在实例化模板化版本使用完全相同的声明的时候。
emmmm…我知道这一块的资料好乱。。。。。。
在C++的官方文档上找到了说明:
可以存在模板构造函数,如下例:
template<typename T1>
struct string {
// member template function
template<typename T2>
int compare(const T2&);
// constructors can be templates too
template<typename T2>
string(const std::basic_string<T2>& s) {
/*...*/ }
};
// out of class definition of string<T1>::compare<T2>
template<typename T1> // for the enclosing class template
template<typename T2> // for the member template
int string<T1>::compare(const T2& s) {
/* ... */ }
但是析构函数和符志构造函数不能带上模板:
析构函数和复制构造函数不能是模板。如果声明了可以用复制构造函数的类型签名实例化的模板构造函数,则使用隐式声明的复制构造函数。
成员函数模板不能是虚的,派生类中的成员函数模板不能重写基类中的虚拟成员函数。
class Base {
virtual void f(int);
};
struct Derived : Base {
// this member template does not override Base::f
template <class T> void f(T);
// non-template member override can call the template:
void f(int i) override {
f<>(i);
}
};
模板成员函数
可以声明具有相同名称的非模板成员函数和模板成员函数。如果发生冲突(当某些模板专用化与非模板函数签名完全匹配时),除非提供显式模板参数列表,否则使用该名称和类型将引用非模板成员。
template<typename T>
struct A {
void f(int); // non-template member
template<typename T2>
void f(T2); // member template
};
//template member definition
template<typename T>
template<typename T2>
void A<T>::f(T2)
{
// some code
}
int main()
{
A<char> ac;
ac.f('c'); // calls template function A<char>::f<char>(int)
ac.f(1); // calls non-template function A<char>::f(int)
ac.f<>(1); // calls template function A<char>::f<int>(int)
}