我想在设计c ++类时了解一些最佳实践。
要把它放在上下文中,我有一个名为Vec3的c ++类。
class Vec3{
private:
float elements[3];
public:
Vec3(Vec3 v1){...}
Vec3(int x, int y, int z){...}
Vec3 add(Vec3 v1){...}
Vec3 add(int x, int y, int z){...}
...
Vec3 multiply(Vec3 v1){...}
...
int dotProduct(Vec3 v1){...}
Vec3 normalize(){...}
....
int operator[](int pos){...}
};
所以,我有这个类在大小为3的Vector上进行计算。 我想知道什么更好。是否使用指针。
我应该返回指针并将参数设置为指针。
Vec3添加(Vec3 v1)或Vec3 *添加(Vec3 v1)或Vec3 *添加(Vec3 * v1)或....
现在我很困惑,我不知道我是否应该在课堂上使用指针。我想总有一种方法可以将我的参数发送到不处理指针的函数...
Vec3* v2 = new Vec3(1,1,1);
Vec3 sum = v1.add(*v2);
有一个解决方案可能是我能想到的最好的解决方案.. 有两个功能
Vec3 add(Vec3 v2){...}
Vec3* add(Vec3* v2){...}
但我担心这会导致代码重复,可能会产生开销。
感谢您的回答...顺便说一句,我可以使用模板来更改Vector的大小,但我更喜欢单独保留Vec3类并创建Vec4类或将其命名为Quaternion。
修改 这是我带来的解决方案。随意评论或修改或重用代码。 一件事。我只想提一下,在我的情况下,这个类应该是透明的。就像我们添加数字一样。
int i = 10;
int j = 15;
int k = i + k;
如果add重载修改了在这种情况下调用函数的对象i。 我最终会得到一个k是对i的引用而我等于25.但我们真正想要的是k等于25且i,k不变。
这就是我班上的工作方式。 Vec3 k = i + k不会修改i或k,因为我们正在根据这些值创建一个新数字。我返回引用的唯一情况是+ =, - =,++, - ...,set([XYZ])?并且正常化。
做一些像myvec.setX(10).normalize()。scale(10)
这样的事情会很有趣。注意:比例应返回参考。我没有看到它,但我想这应该更好。
Vec3 t = myvec.normalize().scale(100).copy();
谢谢大家,我现在正在开发Matrix课程。
答案 0 :(得分:8)
这些是我通常坚持的规则。注意'通常',有时候有理由采取不同的做法......
对于参数我不打算修改我传递的值,如果它们不是太大,因为它们将被复制。如果它们有点大或不可复制,你可以使用const引用或指针(我更喜欢const引用)。
对于我打算修改的参数,我使用引用。
对于返回值,我会尽可能地返回副本。有时候返回引用很方便(这对于获取/设置的单个函数很有用,在获取或设置项目时不需要进行任何特殊处理)。
在我看来,指针确实闪耀的地方是变量,我想在构造或破坏时控制它。
希望有所帮助。
答案 1 :(得分:3)
由于int是原始的,所以保持原样。对于任何有vec3使用参考的东西。
例如
Vec3 add(const Vec3 &v1){...}
在C中你会使用指针,但在c ++中,对象的引用通常更好。
答案 2 :(得分:3)
向量具有已知的语义(为您和您的类的用户所知),所以我会考虑重载运算符(+, - ,+ =, - =)这样做,我会使用常规定义而不是更改它们:
// instead of add:
class Vec3 {
public:
Vec3& operator+=( Vec3 const & rhs );
};
// implemented as free function:
Vec3 operator+( Vec3 const &lhs, Vec3 const & rhs);
我会避免使用指针。引用更自然,只有一小部分情况你需要它们而不是引用/值。避免重复你的函数(有/没有指针)因为这会使你的代码不必要地变得更复杂,正如你已经在问题中发布的那样,你总是可以取消引用指针来检索引用。
提供常量和非常量运算符[]:
class Vec3 {
public:
float operator[]( size_t pos ) const; // returns copy, data does not change
float& operator[]( size_t pos ); // returns a reference and allows changing the contents
};
编辑:我忘了提及size_t细节:首选使用unsigned / size_t作为索引参数而不是有符号整数。
答案 3 :(得分:1)
如果您实施operator+=()
和operator*=()
等运营商,则需要将*this
作为Vec3&
返回。
Vec3& operator+=(const Vec3& v2) {
// add op
return *this;
}
对于其他基本操作员,例如operator+()
和add()
,您需要返回副本:
Vec3 operator+(const Vec3& v2) {
Vec3 ret;
// add
return ret;
}
答案 4 :(得分:1)
在这种情况下,你几乎肯定不希望参数成为指针。考虑这个例子的原因:
// Error: not possible to take the address of the temporary
// return value.
v2.add(&someFunctionReturningVec3());
对于常量的引用没有问题。您甚至可以轻松地嵌套操作:
// declaration: Vec3 add(Vec3 const& v);
v2.add(v1.add(v3));
答案 5 :(得分:0)
在这种情况下,不需要将参数作为指针,并且你真的不应该为所有这样的运算符返回一个新对象。
在OO编程中,想法是对实际对象进行操作,例如,具有
void add(Vec3 v1); void multiply(Vec3 v1);
我还要说你应该坚持把Vec3对象作为参数(而不是x,y,z)。如果你只有x,y,z,你可以调用add(Vec3(x,y,z))。
答案 6 :(得分:0)
此页面包含有关此主题的非常好的讨论:http://www.cs.caltech.edu/courses/cs11/material/cpp/donnie/cpp-ops.html
答案 7 :(得分:-2)
正如greyfade所提到的,你应该关注复制语义。在这种情况下,您还应添加以下方法:
class Vec3 {
public:
Vec3(const Vec3& rhs) {
copy(rhs);
}
Vec3 operator=(const Vec3& rhs) {
copy(rhs);
return *this;
}
private:
void copy(const Vec3& rhs) {
// copy state from rhs
}
};