2009-05-22 86 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。)