【发布时间】:2016-05-26 08:10:09
【问题描述】:
以下是一个简单的 C++ 结构和一个用于 3D 向量和 3x3 矩阵的类。如您所见,下标运算符对它们都进行了重载。我从它们返回对数据成员的引用,以便能够分配给vec[0] = 5.0;、mat[0] = vec3(2.0); 和mat[0][0] = 3.0; 等成员。现在我为mat3 声明另一个运算符,加号(+)运算符它不应该修改矩阵本身,但应该返回一个新矩阵作为总和。如何使这个非修改 + 运算符成为const?
矢量
struct vec3 {
typedef double value_type;
vec3::value_type x, y, z;
vec3(const vec3::value_type x,
const vec3::value_type y,
const vec3::value_type z)
: x{x}, y{y}, z{z} {}
vec3(const vec3::value_type w)
: vec3(w, w, w) {}
vec3()
: vec3(0.0) {}
// this works because [] operator is not used
vec3 operator+(const vec3& v) const {
return vec3(this->x + v.x, this->y + v.y, this->z + v.z);
}
vec3::value_type& operator[](const std::size_t index) {
switch(index) {
case 0:
return x;
case 1:
return y;
case 2:
return z;
default:
throw std::invalid_argument("vec3 supports upto 3(0-2) elements");
}
}
};
矩阵
class mat3 {
std::array<vec3,3> val;
public:
using vtype = vec3::value_type;
mat3(const vtype v00, const vtype v01, const vtype v02,
const vtype v10, const vtype v11, const vtype v12,
const vtype v20, const vtype v21, const vtype v22) {
val[0][0] = v00; val[0][1] = v10; val[0][2] = v20;
val[1][0] = v01; val[1][1] = v11; val[1][2] = v21;
val[2][0] = v02; val[2][1] = v21; val[2][2] = v22;
}
mat3(const vtype m[3][3]) {
for(std::size_t i = 0; i < 3; ++i) {
for(std::size_t j = 0; j < 3; ++j) {
val[i][j] = m[j][i];
}
}
}
mat3(const vtype v)
: mat3(v, v, v,
v, v, v,
v, v, v) {}
mat3()
: mat3(0.0) {}
// how to make it `const`
mat3 operator+(const mat3& m) {
mat3 t;
for(std::size_t i = 0; i < 3; ++i) {
t[i] = val[i] + m[i];
}
return std::move(t);
}
vec3& operator[](const std::size_t index) {
switch(index) {
case 0:
return val[0];
case 1:
return val[1];
case 2:
return val[2];
default:
throw std::invalid_argument("mat3 supports upto 3(0-2) vec3");
}
}
};
【问题讨论】:
-
您没有提供
const版本的operator []是否有特殊原因? (老实说,对于这两个,但对于vec3,至少)。 -
@WhozCraig 我不知道除了这个之外还可以添加另一个 const 版本。
-
你还没有 const 版本,所以不涉及“another”和“besides”;只有“除了”,是的,你可以。
-
是的,
another想表示这个运算符的另一个版本,我认为只有参数类型在重载中才重要,而不是返回类型,现在很清楚了。 -
return std::move(t);应该是return t;。这已经是一个移动上下文,你的版本禁止 NRVO