在c ++中返回对象的最佳方法?

时间:2011-04-24 00:30:21

标签: c++

对于c ++来说,我很吵,返回对象的更好方法是什么?我来自脚本世界,其中对象总是被引用,并且我试图实现相同的概念......我基于When to pass by reference and when to pass by pointer in C++?,其中一个用户说:“一个好的经验法则: “必要时可以使用引用,必要时可以使用引号”。

// basic layer class
class Layer { private: Channel channel; // NEVER NULL };

// return object by pointer
Channel *Layer::getChannel() {
    return &channel;
};

// return by reference
Channel& Layer::getChannel() {
    return channel;
};

第二个版本的问题是编译器会接受这一行:

Channel channel = layer.getChannel();  // creates a copy BAD

应该是:

Channel &channel = layer.getChannel();  // reference good

有没有办法强制第二个选项的调用者强制它不创建新频道,或者是第一个选择更好,即使它永远不会是NULL?

6 个答案:

答案 0 :(得分:11)

您需要调整Channel类本身,使其不可复制。如果它是可复制的,则用户可以复制它,而您所做的任何事情都无法阻止它。

如果复制不是有意义的操作,那么您可以“禁用”它。只需将复制构造函数(Channel(const Channel&))和赋值运算符(Channel& operator=(const Channel&))定义为私有。然后,任何复制类的尝试都将导致编译错误。

另外,正如其他人所提到的,C ++并不是您熟悉的脚本语言。一切都不是一个参考,你只是通过假装来为自己创造一个痛苦的世界。在C ++中,通常在堆栈上分配对象,并按值传递对象,而不是传递引用和指针。

答案 1 :(得分:4)

返回引用(或const引用)是getter方法为调用者提供对成员变量的直接访问的常规方法,因此我建议使用getChannel()的第二个版本。

如果您想阻止来电者制作Channel的不当副本,您可以通过将其复制构造函数设为私有来实现此目的。 (如果你想阻止所有制作副本,甚至是Channel本身,你可以将构造函数声明为私有,然后不实现它。)但是你应该只做这个,如果复制将实际上是荒谬的,例如如果类表示某种无法复制的底层资源。不要仅仅因为您认为调用者不应该需要来禁止复制;这是打电话者做出的决定。

答案 2 :(得分:2)

如果复制对于您的目的而言并不昂贵,并且当您不需要能够更改原件时,请返回对象本身的副本。这应该是默认值。

Channel Layer::getChannel() {     return channel; };

当复制费用昂贵或者您想要更改值时,按引用或指针返回。通过引用返回允许您执行以下操作:

layer.getChannel().clear();

让它作用于该层中的频道。

返回一个指针类似于返回一个引用,除了它给你一点灵活性,因为指针可以指向任何对象。当我希望能够在另一个类中使用“channel”存储时,我经常使用指针。然后我会做

 class MyClass
 {
     // ...
     void setChannel(Channel *pC) { m_pChannel = pC; }
 private:
     Channel * m_pChannel;  // pointer to a channel that came from layer
 }

答案 3 :(得分:1)

即使使用指针返回版本,也无法阻止调用者创建新实例。

Channel* channel = new Channel(*layer.getChannel());

我知道有一种方法可以实现这一目标。 (例如,将Channle的ctor设为私有,只有它的静态成员函数或其友元函数才能创建它。)但是,我不认为这是你的问题。

关键是当你使成员函数返回引用或指针时,你给出了一个调用者选项,他可以选择是否要复制它或引用它。此外,您可以通过添加const使其更加清晰,以使其成为只读。

对于你的情况,我会选择reference-return-version,因为Channel不能为null。如果您不希望它们更改成员变量,请返回const引用。请记住,没有一种最好的方法来决定返回值类型,因为它取决于您想说什么。希望能帮助到你! :)

答案 4 :(得分:1)

由于您正在返回对该对象的引用,因此您可以让该类的用户直接访问该对象,如果您要这样做,为什么要将该对象设为私有?把它公之于众。

答案 5 :(得分:-1)

最重要的是使用您周围的代码保持可读性。 “在罗马做到入乡随俗。”很重要你写了一次,但是每个必须维护代码的人都必须阅读它。如果你的代码突然出现了与你周围的人不同的指导原则,那就意味着他们需要首先找出你的风格,然后弄清楚你在做什么......

我见过的一种方法非常好,就是为你改变的东西提供指针,为你不改变的东西提供const引用:

class Passenger {
  ...
};

class Car {
public:
  int speed() const { return speed_; }
  void set_speed(int speed) { speed_ = speed; }
  const Passenger& passenger() const { return pass_;}
  Passenger* mutable_passenger() { return &pass_; }

private:
  int speed_;
  Passenger pass_;
};

此课程的客户可以:

const Passenger& pass = car.passenger();  // no copy, but don't need to deal with NULL ptrs.

其他建议复制编译错误的答案都很好。