如何在c++中添加两个矩阵
How to add two matrices in c++
我写了一个类,但在添加矩阵时遇到了问题。我知道我必须重载operator+,但我不知道具体是怎么回事。有什么想法吗?
class CMatrix
{
private:
int Rows;
int Columns;
float* pData;
public:
CMatrix(void);
CMatrix(int rows, int columns);
void setElement(int row, int column, float element);
float getElement(int row, int column);
...};
istream& operator>>(istream& in, CMatrix& matrix)
{
in >> matrix.Rows;
in >> matrix.Columns;
for(int i = 0; i < matrix.Rows; i++)
for(int j = 0; j < matrix.Columns; j++)
in >> *(matrix.pData + i * matrix.Columns + j);
return in;
}
CMatrix::CMatrix(int rows, int columns)
{
Rows = rows;
Columns = columns;
pData = new float[Rows * Columns];
float* pEnd = &pData[Rows * Columns];
for(float* p = pData; p < pEnd; p++)
*p = 0.0;
}
void CMatrix::setElement(int row, int column, float element)
{
*(pData+ row * Columns + column) = element;
}
float CMatrix::getElement(int row, int column)
{
return *(pData + row * Columns + column);
}
我重载了运算符的<lt;','>>',但我对operator+有问题。
不幸的是,我只有不到10个声誉。。。所以如果我写:
CMatrix operator+(const CMatrix &lhs, const CMatrix &rhs) { Cmatrix result (Rows,Columns); for(int i=0; i <Rows ; i++) for( int j=0; j<Columns; j++) result.setElement(i,j) = lhs.getElement(i,j) + rhs.getElement(i,j); return result; } int main() { const int n = 10, m = 5; CMatrix m1(n, m); CMatrix m2(n, m); for(int i = 0; i < n; i++) for(int j = 0; j < m; j++) m1.setElement(i, j, (float)(i * m + j)); for(int i = 0; i < n; i++) for(int j = 0; j < m; j++) m2.setElement(i, j, (float)(i * m + j)); cout<<m1+m2; // it doesn't work Thanks all for help, i did it at last...
除非您需要访问CMatrix
的私有成员来执行计算,否则我建议您创建一个具有以下原型的非成员函数:
CMatrix operator+(const CMatrix &lhs, const CMatrix &rhs)
{
// Do the work
// You may need to throw exceptions based on incompatibilities between
// matrix configurations (i.e., dimensions)
}
您还应该添加复制构造函数、析构函数和赋值运算符(可能还有移动构造函数和移动赋值),或者考虑禁用这些操作。如果不这样做,如果代码使用编译器提供的默认值,则会遇到严重问题。
您肯定需要添加一个析构函数,因为如果不添加,就会泄漏内存。
在C++中重载运算符的最佳方法是重载基于分段运算符(operator+=
及其集合)的算术运算符(operator+
、operator-
等)。
在您的情况下:
Matrix& operator+=(const Matrix& other)
{
/* Add operation stuff... */
return *this;
}
Matrix operator+(const Matrix& llhs , const Matrix& rhs)
{
Matrix result( lhs ); //Copy of the first operand.
result += rhs; //Add computation.
return result; //NRVO-friendly implementation
}
这种实现有两个优点:
- 可扩展性:
+
的实现基于+=
。因此,运算符的行为是连贯的,并且是可管理的(没有重复的代码) - 高效:赋值运算符比二进制运算符更便于缓存(您使用同一个实例,使用两个实例并生成结果的实例),并且此实现仅使用一个副本(
result
的实例化中使用的显式副本),因为此代码旨在让编译器执行NRVO
高级主题:自动化运算符重载
您可以利用奇怪的递归模板模式来自动实现运算符重载。
什么是CRTP
CRTP是一个C++习惯用法,其中一个类从模板类继承,并将其作为模板自变量。例如:
template<typename T>
struct Base { /* ... */ };
struct Derived : public Base<Derived> { /* ... */ };
CRTP的关键是基类可以访问(知道)从它派生的类。
操作员自动化:
在我们的例子中,我们可以使用对派生事例的访问来实现基类中的某个运算符,该运算符必须由派生类实现。
让我举一个例子来解释这一点:不等式算子的实现是基于用户提供的等式算子的实现。
template<typename T>
struct EqualityHelper
{
friend bool operator !=(const T& lhs , const T& rhs)
{
return !(lhs == rhs); //We use the operator== that T (The user class) implements.
}
};
我们可以使用该CRTP基作为辅助类来实现从其继承的任何类的operator!=
。例如:
class Foo : public EqualityHelper<Foo> //Magic!
{
friend bool operator==(const Foo& lhs , const Foo& rhs)
{
/* Equality implementation */
}
};
int main()
{
Foo a,b;
if( a != b) //Muahahahaha
{
/* ... */
}
}
这可以扩展到任何操作员。比较运算符是展示这种方法威力的最好例子。整个比较运算符集可以基于其中一个来实现(a > b
是b < a
,a <= b
是!(a > b)
,等等):
template<typename T>
struct ComparisonHelper //Comparison operators based in operator> provided by the user
{
friend bool operator<(const T& lhs , const T& rhs) { return rhs < lhs; }
friend bool operator<=(const T& lhs , const T& rhs) { return !(lhs > rhs); }
friend bool operator>=(const T& lhs , const T& rhs) { return !(lhs < rhs); }
};
最后,我们可以利用多重继承同时使用多个助手:
//The complete set of logical comparison operators in six mantenible lines of code!
class Foo : public EqualityHelper<Foo> , public ComparisonHelper<Foo>
{
friend bool operator==(const Foo& lhs , const Foo& rhs)
{
/* Equality implementation */
}
friedn bool operator>(const Foo& lhs , const Foo& rhs)
{
/* Comparison implementation */
}
}
Boost库有一个标头,其中包含一组使用此方法实现的助手:http://www.boost.org/doc/libs/1_54_0/libs/utility/operators.htm
我会简单地评论Michael Goldshteyn的帖子,但我想我没有足够的声誉来做这件事(哈哈),所以把这看作是对他的帖子的评论:
如果您需要+运算符来访问您的CMatrix类的私有数据(在这种情况下需要这样做),您可以通过插入以下行将此函数声明为您的CMetrix类中的朋友:
friend CMatrix operator+(const CMatrix &, const CMatrix &);
CMatrix类定义中的任何位置。这允许您在其他地方定义的重载运算符函数访问类的私有和受保护成员(如pData成员)。
- 如何在C++中从两个单独的for循环中添加两个数组
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 当在同一名称空间中有两个具有相同签名的函数时,会发生什么
- 如何返回一个类的两个对象相加的结果
- 如何在C++中将一个无符号的 int 转换为两个无符号的短裤?
- 如何将两个不同矢量的同一位置的两个元素组合在一起
- 两个字符串在 c++ 中不相等
- 在两个类中共享相同的函数调用,并在不需要时避免空实例化
- 两个文件使用彼此的功能-如何解决
- 为什么Mat类的两个对象可以在不重载运算符+的情况下添加
- 如何确保在使用基于布尔值的两个方法之一调用方法时避免分支预测错误
- 停止cmake target_link_libraries将插件中静态库的两个对象文件链接到静态库本身
- 将fold表达式与std::一起用于两个元组
- 如何在C++中比较两个char数组
- 给定两个偶数,求出它们之间所有偶数的平方和
- 比较两个大小不等的映射c++
- C++需要帮助从用户那里获得一个整数,并确保它在另外两个整数之间
- 如何在for循环中包含两个索引值的测试条件
- 在声明中合并两个常量"std::set"(不是在运行时)
- 如何使用OpenMP并行这两个循环