[英]C++ class best practice
我想知道设计 c++ 类时的一些最佳实践。
把它放在上下文中,我有一个名为 Vec3 的 c++ class。
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){...}
};
所以,我有这个 class 可以计算大小为 3 的向量。我想知道什么更好。 是否使用指针。
我是否应该返回指针并将我的参数作为指针。
Vec3 add(Vec3 v1) 或 Vec3* add(Vec3 v1) 或 Vec3* add(Vec3* v1) 或....
现在我很困惑,我不知道我是否应该在我的 class 中使用指针。 我想总有一种方法可以将我的 arguments 发送到不处理指针的 function...
Vec3* v2 = new Vec3(1,1,1);
Vec3 sum = v1.add(*v2);
并且有一个解决方案可能是我能想到的最好的解决方案......同时具有这两种功能
Vec3 add(Vec3 v2){...}
Vec3* add(Vec3* v2){...}
但我担心这会导致重复代码并且可能是开销。
谢谢您的回答...顺便说一句,我可以使用模板来更改向量的大小,但我更喜欢单独保留我的 Vec3 class 并创建一个 Vec4 class 或将其命名为四元数。
编辑这是我带来的解决方案。 随意评论或修改或重用代码。 一样东西。 我只想提一下,就我而言,这个 class 应该是透明的。 就像我们添加数字一样。
int i = 10;
int j = 15;
int k = i + k;
如果添加重载修改 object 在这种情况下调用 function i。 我最终会认为 ak 是对 i 的引用,并且 i 等于 25。但是我们在这里真正想要的是 ak 等于 25 并且 i,k 不变。
这就是我的 class 的工作方式。 Vec3 k = i + k 不会修改 i 或 k,因为我们正在从这些值创建一个新数字。 我返回引用的唯一情况是 +=、-=、++、--...、set([XYZ])? 并正常化。
做类似 myvec.setX(10).normalize().scale(10) 这样的事情可能会很有趣
注意:比例应该返回一个参考。 我没有看到它,但我想这样应该会更好。
Vec3 t = myvec.normalize().scale(100).copy();
谢谢大家,我现在将研究 Matrix class。
这些是我通常坚持的规则。 请注意“通常”,有时会有不同的做事方式......
对于我不打算修改的参数,如果它们不是太大,我会按值传递,因为它们将被复制。 如果它们有点大或不可复制,您可以使用 const 引用或指针(我更喜欢 const 引用)。
对于我确实打算修改的参数,我使用参考。
对于返回值,我将尽可能返回一个副本。 有时返回引用很方便(这适用于单个 function 用于获取/设置,在获取或设置项目时不需要进行任何特殊处理)。
在我看来,指针真正闪耀的地方是例如我想要控制何时构造或销毁它的变量。
希望有帮助。
由于 int 是原语,所以保持原样。 对于任何带有 vec3 的使用参考。
例如。
Vec3 add(const Vec3 &v1){...}
在 C 中,您会使用指针,但在 c++ 中,引用通常更适合对象。
向量具有已知的语义(为您和您的类的用户所知),因此我会考虑在这样做时重载运算符(+、-、+=、-=),我将使用常规定义而不是更改它们:
// 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 作为索引参数而不是有符号整数。
如果你实现了 operator 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;
}
在这种情况下,您几乎肯定不希望参数成为指针。 考虑这个例子,了解原因:
// 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));
在这种情况下,不需要将 arguments 作为指针,而且您真的不应该为所有这样的运算符返回新的 object。
在 OO 编程中,想法是对实际的 object 进行操作,例如具有
void add(Vec3 v1); void multiply(Vec3 v1);
我还要说你应该坚持将 Vec3 对象作为 arguments(而不是 x、y、z)。 如果你只有 x,y,z,你可以调用 add(Vec3(x,y,z))。
此页面包含有关此主题的非常好的讨论: http://www.cs.caltech.edu/courses/cs11/material/cpp/donnie/cpp-ops.html
正如 grayfade 提到的,您应该关注复制语义。 在这种情况下,您还应该添加这些方法:
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
}
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.