繁体   English   中英

C++ class 最佳实践

[英]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();

http://pastebin.com/f413b7ffb

谢谢大家,我现在将研究 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM