4

以下语法在 OpenCV 中有效

Mat R = (Mat_<double>(4, 4) <<
        1,          0,           0, 0,
        0, cos(alpha), -sin(alpha), 0,
        0, sin(alpha),  cos(alpha), 0,
        0,          0,           0, 1);

怎么可能?哪个运算符重载了?这个表达的意义是什么?逗号运算符现在可以重载C++吗?

4

3 回答 3

4

逗号运算符可以重载,但通常不建议这样做(在许多情况下,重载的逗号令人困惑)。

上面的表达式为 4*4 矩阵定义了 16 个值。如果您想知道这怎么可能,我将展示一个更简单的示例。假设我们希望能够写出类似的东西

MyVector<double> R = (MyVector<double>() << 1 , 2 , 3);

然后我们可以定义 MyVector 以便<<,运算符将新值附加到向量:

template<typename T> 
class MyVector: public std::vector<T> {
 public:
  MyVector<T>& operator << (T value) { push_back(value); return *this; }
  MyVector<T>& operator , (T value) { push_back(value); return *this; }
  ...
};
于 2013-06-12T21:17:23.973 回答
3

这是取自此处的实际代码,您可以看到operator,正在使用的代码:

template<typename _Tp> template<typename T2> inline MatCommaInitializer_<_Tp>&
MatCommaInitializer_<_Tp>::operator , (T2 v)
{
     CV_DbgAssert( this->it < ((const Mat_<_Tp>*)this->it.m)->end() );
     *this->it = _Tp(v); ++this->it;
    return *this;
}

它获取下一个值并将其简单地放入矩阵中,递增迭代器,然后返回对MatCommaInitializer对象的引用(因此这些运算符可以链接在一起)。

于 2013-06-12T21:28:34.653 回答
2

下面是 OpenCV 的源代码。我们可以知道 MatCommaInitializer_ 类重载了,操作符,并且重载<<了全局静态字段中的操作符。

`
core.hpp
...
template<typename _Tp> class MatCommaInitializer_
{
public:
    //! the constructor, created by "matrix << firstValue" operator, where matrix is cv::Mat
    MatCommaInitializer_(Mat_<_Tp>* _m);
    //! the operator that takes the next value and put it to the matrix
    template<typename T2> MatCommaInitializer_<_Tp>& operator , (T2 v);
    //! another form of conversion operator
    Mat_<_Tp> operator *() const;
    operator Mat_<_Tp>() const;
protected:
    MatIterator_<_Tp> it;
};
...
`

`
mat.hpp
...
template<typename _Tp, typename T2> static inline MatCommaInitializer_<_Tp>
operator << (const Mat_<_Tp>& m, T2 val)
{
    MatCommaInitializer_<_Tp> commaInitializer((Mat_<_Tp>*)&m);
    return (commaInitializer, val);
}
...
`

所以你的代码的工作过程如下:

  1. Mat_(4, 4) 创建一个包含 4 行 4 列 double 类型元素的实例。

  2. 然后它调用<<重载的运算符并返回 MatCommaInitializer_ 实例。

  3. 然后它调用,重载的运算符并返回 MatCommaInitializer_ 实例,依此类推。

  4. 最后调用构造函数Mat(const MatCommaInitializer_<_Tp>& commaInitializer)

于 2015-12-15T04:51:09.240 回答