“core.hpp”
template<typename _Tp, int m, int n> class Matx
{
public:
typedef _Tp value_type;
typedef Matx<_Tp, (m < n ? m : n), 1> diag_type;
typedef Matx<_Tp, m, n> mat_type;
enum { depth = DataDepth<_Tp>::value, rows = m, cols = n, channels = rows*cols,
type = CV_MAKETYPE(depth, channels) };
//! default constructor
Matx();
Matx(_Tp v0); //!< 1x1 matrix
...
Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3,
_Tp v4, _Tp v5, _Tp v6, _Tp v7,
_Tp v8, _Tp v9, _Tp v10, _Tp v11,
_Tp v12, _Tp v13, _Tp v14, _Tp v15); //!< 1x16, 4x4 or 16x1 matrix
explicit Matx(const _Tp* vals); //!< initialize from a plain array
explicit的含义是,告诉编译器,我这句话必须由程序员调用,你不可以背着程序员干这件事。
目的是为了消除由于编译器隐式调用这句话,导致的逻辑错误。这个错误不会被编译器发现,所以一般很难找到。
这句构造函数,一般什么时候会被隐式调用呢?
int p[4] = {1,2,3,4};
Matx<float,2,2> m(p); //显式调用
Matx<float,2,2> m = p; //先隐式调用Matx(const _Tp* vals),再调用默认复制构造函数
//由于explicit修饰,第一步隐式调用不允许,这句话编译不通过
我觉得有两点考虑:
1. 避免错误(上面提到的,但是目前对编译器在哪些情况下会隐式调用,不清楚)
2. 为了代码的可读性。从人的直观理解,等号两边应该是相同类型,这样会比较安全。如果编译器允许了m=p,总会让人很疑惑,“为什么int数组可以赋值给Matx”,这种感觉违背了对等号的直观感受,不利于代码的可读性。而使用m(p)就很好理解,它调用了函数,函数里面做了相应的事情来构造一个Matx。