C ++类最佳实践

时间:2009-03-09 04:34:35

标签: c++ class

我想在设计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();

http://pastebin.com/f413b7ffb

谢谢大家,我现在正在开发Matrix课程。

8 个答案:

答案 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
  }
};