对于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?
答案 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.
其他建议复制编译错误的答案都很好。