顺便说一句:我正在寻求回答这个问题的部分内容。我也不寻求在其他有价值的答案中复制所有信息。赏金寻求与所问问题不同的东西,所以我没有回应。
提供矩阵乘法实际上相当简单。由于我不打算描述数据结构来表示矩阵并完全实现对它们的操作和有效性检查,因此我将仅提供框架来说明。
示例 1:operator*() 作为成员函数
class M // a basic matrix class
{
public:
// assume other constructors and members to set things up
M operator*(const M &rhs) const;
};
M M::operator*(const M &rhs) const
{
// implement checks on dimensions, throw an exception if invalid
M result;
// implement the multiplication (typical iterations) and store results in result
return result;
}
int main()
{
M a;
M b;
// set up elements of a and b as needed
M c = a*b; // this relies on M having appropriate constructor(s) to copy or move the result of a*b into c
M d;
d = a * b; // this relies on M having appropriate operator=() to assign d to the result of a*b
}
上面实现了operator*()作为成员函数。所以,在功能上,c = a*b 等价于c = a.operator*(b)。 const 限定符表示矩阵乘法 a*b 通常不会更改 a 或 b。
示例 2:operator*() 作为非成员函数
现在,operator*() 也可以实现为非成员(可选friend),其骨架看起来像
class M // our basic matrix class, different operator *
{
public:
// assume other constructors and members to set things up
friend M operator*(const M &lhs, const M &rhs);
};
M operator*(const M &lhs, const M &rhs)
{
// implement checks on dimensions, throw an exception if invalid
M result;
// implement the multiplication (typical iterations) and store results in result
return result;
}
// same main() as before
请注意,在这种情况下,a*b 现在等同于 operator*(a, b)。
如果您想同时使用这两种形式,则需要注意避免歧义。如果提供了operator*() 的两种形式,则它们在c = a*b 之类的语句中都是有效匹配项,并且编译器无法选择一种形式而不是另一种形式。结果是代码无法编译。
示例 3:重载operator*()
还可以重载operator*() - 例如,将矩阵乘以标量。
class M // a basic matrix class
{
public:
// assume other constructors and members to set things up
M operator*(const M &rhs) const; // as in first example
M operator*(double scalar) const; // member form
friend M operator*(double scalar, const M &rhs); // non-member form
};
M M::operator*(double scalar) const
{
M result;
// implement the multiplication (typical iterations) and store results in result
return result;
}
M operator*(double scalar, const M &m)
{
M result;
// implement the multiplication (typical iterations) and store results in result
return result;
}
int main()
{
M a;
M b;
// set up elements of a and b as needed
M c = b * 2.0; // uses the member form of operator*() above
M d;
d = 2.0*a; // uses the non-member form of operator*() above
}
以上b*2.0相当于b.operator*(2.0)的调用和2.0*a非会员operator*(2.0, a)的调用。成员形式通常只能用于左侧操作数为M 类型的表达式。因此,如果只提供operator*() 的成员形式,2.0*a 将不起作用。
讨论
除了对上述歧义的担忧之外,在重载运算符时还需要注意其他事项。
- 无法根据语言规则中的规范更改运算符的优先级或关联性。因此,在表达式
a+b*c 中,* 的优先级总是高于+。这也是在 C++ 中重载 ^ 以进行幂运算不是一个好主意的原因,因为 ^ 在 C++ 中的优先级低于 +(作为整数类型的按位运算)。因此,a + b^c 在 C++ 中实际上等同于 (a + b)^c,而不是 a + (b^c)(任何具有代数基础知识的人都会想到)。
- 该语言指定了一组运算符,并且无法创建新的运算符。例如,C++ 中没有
**,因此a ** b 将a 提升到b 的幂(其他语言可以做到),并且不可能创建一个。
- 并非所有运算符都可以重载。
在 C++ 中不能重载的运算符之一是 .*。所以不可能像在 Matlab 中那样使用这样的运算符。我通常建议不要尝试使用其他运算符获得相同的效果,因为上述约束会影响这一点(并导致表达式给出违反直觉的行为)。相反,只需提供另一个命名函数来完成这项工作。比如作为成员函数
class M
{
public:
// other stuff
M ElementWiseProduct(const M &) const;
};