模板类中的 c++ 赋值运算符实现

Posted

技术标签:

【中文标题】模板类中的 c++ 赋值运算符实现【英文标题】:c++ assignment operator implementation in templated class 【发布时间】:2011-05-23 04:20:15 【问题描述】:

我正在构建自己的矩阵类来巩固我对 C++ 的理解。它是模板化的,所以我可以有一个 int 矩阵或一个浮点数或布尔矩阵。我不打算实现复制构造函数或赋值运算符或析构函数,因为我不会有任何动态成员元素,但如果我有:

Matrix<float,3,4> mat1;
Matrix<int,45,45> mat2;
mat1 = mat2;

它返回以下错误:

/Users/Jake/Dropbox/C++/test.cpp: In function ‘bool test1()’:
/Users/Jake/Dropbox/C++/test.cpp:23: error: no match for ‘operator=’ in ‘m2 = m1’
/Users/Jake/Dropbox/C++/Matrix.h:22: note: candidates are: Matrix<float, 3u, 4u>& Matrix<float, 3u, 4u>::operator=(const Matrix<float, 3u, 4u>&)

其中,如果两个矩阵都是浮点数或整数,没关系。尺寸不必匹配。因此,除非它们属于不同类型,否则默认赋值运算符效果很好。所以我实现了自己的赋值运算符:

template <class T, unsigned int rows, unsigned int cols>
template <class T2, unsigned int rows2, unsigned int cols2>
Matrix<T, rows2, cols2> & Matrix<T,rows,cols>::operator= (const Matrix<T2, rows2, cols2> & second_matrix)
        unsigned int i,j;
for (i=0; i < rows2; i++)
    for (j=0; j < cols2; j++)
        data[i][j] = second_matrix(i,j);    
    

this->_rows = rows2;
this->_cols = cols2;
return *this;

如果它们是不同的类型,但尺寸相同,则此方法有效 - 但第二个中的值从第二个类型转换为第一个。我的问题是,我该如何设置它,以便它们可以是不同的类型和不同的尺寸,并且只需将其设置为指向第二个或第二个的副本?

【问题讨论】:

我怎样才能设置它,以便它们可以是不同的类型和不同的尺寸,并且只需将其设置为指向第二个或第二个的副本? 它已经解释过你不能,C++ 阻止你对矩阵理论中不存在的矩阵执行操作——你不能分配矩阵,其维度不相同。 【参考方案1】:

您遇到的问题是您有三种类型,但您只提到了两种。从根本上说,

Matrix<float,3,4> mat1;
Matrix<int,45,45> mat2;
mat1 = mat2;

不能工作,因为赋值的结果应该是Matrix&lt;float, 45, 45&gt;,但mat1的类型是Matrix&lt;float, 3, 4&gt;。这不可能改变。

矩阵的维度必须是类型的一部分是否有原因?看起来你真的想让这些东西动态地改变。就这样吧:'

template <class T>
class Matrix

    unsigned int rows;
    unsigned int cols;
  public:
    Matrix(numrows, numcols): rows(numrows), cols(numcols) 
;

等...然后您可以在运行时更改矩阵的维度。

【讨论】:

正是我的想法?为什么矩阵的维度是类型的一部分而不是其中的变量? 但这是一个完全不同的 Matrix 类,它不再在堆栈上,它必须动态分配它的元素。通常,由于密集矩阵上的操作非常慢,因此大小不会那么大,因此为了提高性能,使用堆栈分配的矩阵是有利的。 如果您问我,我更喜欢将维度放入类型中,因为我认为更改矩阵的维度没有任何意义。但是,发帖人想要执行该任务,这就是结果。 好的,我理解它基本上归结为设计选择。我不想动态分配数据,所以我只需要坚持我为每个矩阵设置的参数,是吗?我以为我可以同时拥有它,但我知道我必须如何选择。谢谢大家。【参考方案2】:

我如何设置它,以便它们可以是不同的类型和不同的尺寸,并且只需将其设置为指向第二个或第二个的副本?

你没有。

mat 不指向Matrix&lt;float,3,4&gt;;它是Matrix&lt;float,3,4&gt;。它永远不可能是别的东西。没有办法将mat 变成Matrix&lt;int,45,45&gt;

如果希望能够指向不同的对象,则需要使用指针(或引用)。为了能够拥有一个可以指向Matrix 的任何特化的指针,您需要创建一个基类并从该基类派生Matrix

class MatrixBase  ;

template <typename T, unsigned Rows, unsigned Columns>
class Matrix : public MatrixBase  ;

然后您可以使用MatrixBase* 指向任何Matrix 类型的对象,并且您可以使用MatrixBase&amp; 来引用任何Matrix 类型的对象。您需要将尽可能多的共享功能放入MatrixBase 类或使用虚函数。

【讨论】:

您确定要将RowsCols 设为typename 而不是unsigned int 吗? @TokenMacGuy:你什么意思?他们是unsigned! :-O(谢谢,哈哈)

以上是关于模板类中的 c++ 赋值运算符实现的主要内容,如果未能解决你的问题,请参考以下文章

永恒赋值运算符调用循环C++模板类

带有模板类的赋值运算符 - 没有可接受的转换,C++

模板类赋值运算符类

C++第六天笔记2016年02月23日(周二)A.M

在c ++中的赋值运算符重载方法中删除旧的动态分配的内存

重载“着色器”类中的赋值运算符