2009-05-22 84 views
1

关于const成员函数的返回值是否应该是const或者不是const的一个好的经验法则是什么?以下是我倾向于做的事情,但我很难与 模糊的情景。从const成员函数返回对象的常量

class foo 
{ 
    public: 
     // if the returned object is conceptually 
     // (and therefore usually literally but not even necessarily) 
     // owned by *this*, 
     // then a const ptr should be returned 
     const ownedByFoo *getOwnedByFoo() const { return m_ownedByFoo; } 
     ownedByFoo *getOwnedByFoo() { return m_ownedByFoo; } 

     // what's a poor boy to do here? 
     // veryRelatedToFoo might be a conceptual contemporary or parent 
     // of Foo. Note naming the function "find..." instead of "get.." 
     // since *get* implies the object holds it as a data member but 
     // that may not even be the case here. There could be a 
     // standalone container that associates foo and veryRelatedToFoo. 
     // Should constness be symmetrical here? 
     const veryRelatedToFoo *findVeryRelatedToFoo() const; 
     veryRelatedToFoo *findVeryRelatedToFoo(); 

     // If the returned object is only (conceptually) 
     // peripherally related to *this*, 
     // the returned object probably shoudn't be const, even if 
     // foo happens to have one of these as a direct data member, 
     // since we don't want to give away the implementation details of 
     // Foo and it may hold peripherallyRelatedToFoo simply for performance 
     // reasons, etc. 
     peripherallyRelatedToFoo *findPeripherallyRelatedToFoo() const 

    ... 
}; 

另外一个需要注意的是,一旦你有不对称的常量性,你可以 问const对象A返回对象B,然后问对象B返回对象A,并 那么你已经成功绕过预期对象A的稳定性。

回答

1

任何常量都比你在许多语言中找到的要多!一旦你理解了“物理常量”和“逻辑常量”之间的差异,那么'不明确'的场景仍然只是:受争议。例如,考虑关键字mutable存在的事实。

我认为你有正确的总体思路:超越,这一切都值得商榷,主观和变化根据特定的问题和制约因素等

我倾向于选择“无例外的规则”,所以我避免从const方法返回指向非const的指针;但我想我可以想象一些我可能会被诱惑的场景......尽管我可能更倾向于决定让这个方法非const。

1

(我忽略了你是返回对象的状态直接样子,这通常是一个坏主意,因为它打破了封装的事实 - 我在看这个“样本代码”)

有这两者之间没有任何关系。 A const成员函数是不修改底层对象的成员 - “在执行时”。没有承诺或要求返回值为const或不。一旦该方法返回,const-性合约就会“结束”。我想你会感到困惑,因为你正试图将返回值与生成它的方法连接起来。

返回值是否应为constconst完全取决于返回值的性质以及您希望赋予方法的语义。

在您的具体第一种情况下,这两种方法应返回相同的const -ness。 const重载可能不是你想要使用的。如果你想在两个变化,我可能会使其明确的,像这样的:

const ownedByFoo *getOwnedByFoo() const { return m_ownedByFoo; } 
ownedByFoo *getOwnedByFooForEdit() { return m_ownedByFoo; } 

这样没有歧义和两个没有神秘的搭售。请注意,我做了第二个非const,因为我们可能不希望客户端代码修改const对象上的m_ownedByFoo。这是由方法的语义(“返回内部状态”)产生的一个要求,而不是脱离方法的const-与返回值的const-之间的联系。如果返回的值不是对象状态的一部分,我可能会做其他事情。

+1

从技术上讲,你说的是正常合同,但这是一种过于字面的解释。当你无意中问一个物体(如在常量中)交出一块自己的物体时,你会得到一个非const对象的装载枪(然后你可以修改你的心)。该方法是一个特洛伊木马进入你的对象。 你的第二点很好。我认为人们通常习惯于重载签名,因为他们可以在const和non-const情况下的任何地方使用相同的get方法,而无需考虑它,但让调用者思考它通常是件好事 – 2009-05-22 20:02:27

0

不要从const方法返回非const指针或对成员数据的引用。

0

如果返回的引用是const,则使函数为const,如果不是,则不要。您应尽量避免将非const引用返回给成员数据,尽管因为这会破坏封装,除非该类主要是某种容器类。

0

如果返回非const引用/指针将允许调用者使该类应该维护的不变量失效,则不要返回该非const引用/指针。 (它应该是const。)