2011-09-22 54 views
1

我目前正在研究C++類。該類的目的是做一些http查詢。您創建一個實例指定C++:這是一個有效的常量成員函數嗎?

  • 目標網址
  • 其它一些參數

憑藉這種情況下,你可以調用一個名爲「的getChildren」它連接到HTTP服務器,方法執行查詢並返回一個孩子的名單。所以基本上,它看起來與此類似:

class HttpRequest 
{ 
    public: 
    // omitted constructor, ... 
    const std::list<Child> getChildren() { 
     // do the http query 
     // build a list 
     return(list); 
    } 
} 

這是由「的getChildren」返回可能會改變每個呼叫的名單 - 這取決於HTTP服務器上完成其他操作。現在,你怎麼看:我應如何申報方法:既然 「的getChildren」 不修改的HttpRequest

  • const std::list<Child> getChildren();
  • const std::list<Child> getChildren() const;

它會以兩種方式進行編譯。

感謝您的幫助, 烏利

回答

1

一般的經驗法則是,如果你可以聲明一個成員函數爲const。如果getChildren進行了一些修改,似乎改變了HttpRequest對象的狀態(即使它實際上沒有改變狀態),但可能應該聲明它爲非常量以避免讓人困惑。但除此之外,它應該是const

另外,我明白你爲什麼聲明返回值的邏輯是const。我仍然建議你不要那樣做。使用C++ 11和移動構造函數等,它實際上非常有用(更準確),因爲它是非const的。

+0

感謝您的建議。我會考慮返回值的'const'(...副本)。 – user959232

1

如果你的意圖是確保函數不改變HttpRequest對象的狀態,那麼你想要std::list<Child> getChildren() const。沒有理由使std::list不變,除非你返回一個參考。

+0

非常感謝。目前,我正在考慮通過參考返回列表。如果我決定不這樣做(...並保留副本),那麼我將刪除'const'。 – user959232

2

我最初的直覺反應是,如果很難決定,我們應該更詳細地看看函數。此外,由於HttpRequest狀態沒有發生變化,並且每次都可能返回一個不同的值,所以函數可能根本不應該是成員。看起來,作爲非會員,非朋友,使用HttpRequest來執行其工作並返回一個值可能更有意義。那麼常量語義是清楚的。

+0

感謝您的建議。不幸的是,這裏的情況很棘手。我們確實有不止一個'HttpRequest'。我們使用基於'HttpRequest'的類層次結構,並且每個派生類都有一個方法'getChildren'。其中一些返回在創建對象時填充的成員變量的值。其他人在調用'getChildren'時執行http查詢。對於第一組,我認爲目前的聲明非常好。對於另一組,它可能不同。我會考慮你的建議......謝謝! – user959232

3
  • const std::list<Child> getChildren();
  • const std::list<Child> getChildren() const;

它將這兩種方式編譯,因爲 「的getChildren」 不修改的HttpRequest。

  1. 不,這不會編譯兩種方式。 (如果會的話,那裏會有什麼不同?) 第二種形式是必需的調用getChildren()const HttpRequest對象(或引用或指針):

    void f(const HttpRequest& req) 
    { 
        const std::list<Child>& list = req.getChildren(); // requires const 
        // ... 
    } 
    

    這將需要後const

  2. 返回類型頂層constconst std::list<Child>)根本沒有任何區別。返回的對象是一個右值。你所能做的只是製作一個副本或將其綁定到const std::list<Child>&--無論是否爲const

  3. 你很可能並不想複製這樣的列表,每次getChildren()被稱爲被複制,所以你應該返回參考

    const std::list<Child>& getChildren() const; 
    

    (當然,如果有不同步參與,您可能需要複製,而不是分發對潛在異步更改對象的引用。)

  4. 您可以根據尾隨const進行重載。鑑於這種情況,你可以有兩個版本:一個是改變列表和一個用於獲取一個const列表參考:

    const std::list<Child>& getChildren() const; 
         std::list<Child>& getChildren(); 
    

    我不知道這是否讓任何意義,你的情況。

+0

在這種情況下,複製可能是一個非問題 - 如果列表的大小合理,那麼花在複製上的花費與花在創建http請求上的費用相比可能可以忽略不計,並且可以實現更簡單的代碼。要返回一個引用,HttpRequest將不得不存儲一個副本,他必須小心,在他完成清單之前不要銷燬HttpRequest對象... – Eclipse

+0

這忽略了NRVO和C++ 11的r值構造函數。 – Eclipse

+0

非常感謝您的反饋和解釋。實際上,我目前正在重構該方法 - 我從其他開發人員繼承了它。之前,它用來返回引用。但不幸的是,對象存儲在本地變量,所以這可能不是一個好辦法。所以:我現在保留「複製」。也許以後我會使用類似智能指針的東西。謝謝你的幫助。 – user959232