【发布时间】:2015-10-26 02:01:30
【问题描述】:
我在自己的库中编写了一个通用的 Matrix 类,其中包含 +、-、* 等不错的运算符。特别是它有(函数体并不重要,你可以忽略它们,但我稍后还是会引用它,所以有它很好):
template<typename T, int X, int Y>
Matrix<T,Y,X> operator*(const Matrix<T,Y,X> & left, const Matrix<T,Y,X> & up)
{
Matrix<T,Y,X> result = Matrix<T,Y,X>::Zero;
for (unsigned int j = 0; j<Y; j++)
for (unsigned int i = 0; i<X; i++)
for (unsigned int k = 0; k<X; k++)
result[j][k] += left[j][i] * up[i][k];
return result;
}
template<typename T, int Y, int X, typename U>
Matrix<T,Y,X> operator*(const Matrix<T,Y,X> & left, const U & right)
{
// Expected to handle build-in types
Matrix<T, Y, X> result = Matrix<T, Y, X>::Zero;
for (int j = 0; j < Y; ++j)
for (int i = 0; i < X; ++i)
result[j][i] += left[j][i] * right;
return result;
}
然后我写了Matrix4x4,Matrix 的一个子类型,专门用于旋转和平移等 3D 转换,因此它具有用于此目的的成员函数。当然,Matrix4x4 是个坏名字,我保证我会解决这个问题。
在使用Matrix4x4 的代码中的某个点我使用operator*:
// std::vector<Matrix4x4> mstackvertices({Matrix4x4::Identity});
mstackvertices.push_back(mstackvertices.back() * m_camera.m_projectionmatrix);
这里的m_camera.m_projectionmatrix 也是Matrix4x4。
这应该调用第一个 operator*,但属于第二个,因为 gcc 在第二个重载中给我一个错误,在以下行:
result[j][i] += left[j][i] * right;
错误信息:
Matrix.hpp|169|error: no match for ‘operator*’ (operand types are ‘const float’ and ‘const swegl::Matrix4x4’)|
Matrix.hpp|169|note: candidates are:|
...
我的猜测是 Matrix4x4 不完全是 Matrix,而只是一个子类型,一些规则适用于使 gcc 选择不涉及类型转换的最佳重载。
我不确定如何解决这个问题。我已经考虑了几种解决方案,但似乎都不是很好:
- 删除将接收内置类型的运算符,从而强制编译器选择唯一剩余的重载。这可行,但迫使我从看似完美的库中删除一个功能。
- 使用组合而不是继承,并根据
Matrix重载所有相关的Matrix4x4运算符。 - 在
Matrix4x4中重新实现operator*。会有重复的代码,或者,如果我能设法通过强制转换调用正确的Matrix::operator*重载,那仍然会很麻烦。 - 创建
Matrix4x4::operator Matrix<float,4,4>()。它似乎不起作用,但我也可能在那里做错了什么。无论如何,我知道这会创建一个不受欢迎的对象副本。
这就是我现在的位置。还有什么想法吗?也许我首先做错了什么? 我相信我会从中学到一些东西,所以非常欢迎任何帮助(:
编辑:
Matrix 和 Matrix4x4 的定义如下:
template<typename T, int Y, int X>
class Matrix
{
private:
T data[Y][X];
...
};
class Matrix4x4 : public Matrix<float,4,4>
{
...
};
【问题讨论】:
-
我们是否应该猜测模板参数是什么,或者
Matrix和Matrix4x4的定义是什么样的? -
认为这无关紧要。无论如何,善意地询问会有所帮助。
-
AxB 乘以 BxC 而不是 AxB。
-
typename U在第二个函数中被推导出为Matrix4x4 const&,这比Matrix<float,4,4> const&更好的匹配,你必须限制可以与 SFINAE 一起使用的第二个函数的类型.另请注意,函数返回Matrix<T,Y,X>而不是派生类,这可能不是您想要的。 -
是的,@Yakk。为了便于阅读,我选择简化代码。
标签: c++ inheritance operator-overloading