模板构造函数

模板构造函数不同于模板类
使用模板的作用有以下两个好处:
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)
}

猜你喜欢

转载自blog.csdn.net/weixin_39326879/article/details/110916578