2011-04-24 48 views
13

對於C++來說,我很不喜歡,返回對象的最好方法是什麼?我來自腳本世界,對象總是引用,並試圖實現相同的概念...我基於此從When to pass by reference and when to pass by pointer in C++?,其中一個用戶表示:「一個很好的經驗法則:」使用引用時你可以和指針,當你不得不「。」在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?

+9

「我是從腳本世界裏,對象總是引用過來,並試圖實現同樣的想法:」你爲什麼想通過周圍的一切,在C++的引用?在C++中這是不自然的。您引用的「經驗法則」可能會更好地聲明爲「儘可能使用值(和副本),否則使用引用,並且僅作爲最後手段使用指針。」 – 2011-04-24 00:31:36

+0

考慮到您的背景,我強烈建議您瞭解**智能指針**,以便爲堆分配對象獲取自動內存管理。 – 2011-04-24 01:48:17

回答

11

您需要調整Channel類本身,以便它是不可拷貝。如果它是可複製的,用戶可以複製它,而你所做的任何事都可以阻止它。

如果複製不是一個有意義的操作,那麼你可以「禁用」它。只需將複製構造函數(Channel(const Channel&))和賦值運算符(Channel& operator=(const Channel&))定義爲私有。然後,任何嘗試複製類都將導致編譯錯誤。

在一個側面說明,如其他人所說,C++是不是腳本語言您熟悉。一切都不是一個參考,你只是通過假裝否定了自己的痛苦世界。在C++中,通常在堆棧中分配對象,並按值傳遞對象,而不是傳遞引用和指針。

4

返回引用(或const引用)是getter方法爲調用者直接訪問成員變量的正常方式,所以我建議使用getChannel()的第二個版本。

如果您想防止呼叫者製作不合適的Channel副本,您可以通過將其複製構造函數設爲私有來實現。 (如果你想阻止的一切製作拷貝,甚至Channel本身,你可以聲明構造函數是私人的,然後不執行它)。但是,如果複製實際上是無意義的,你應該這樣做。如果該類表示某種不能被複制的底層資源。不要因爲你認爲調用者不應該複製需要;這是來電者做出的決定。

2

當複印對於您的目的而言並不昂貴並且您不需要更改原稿時,請返回對象本身的副本。這應該是默認的。

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

當複印費用昂貴或者您可能需要更改值時,通過引用或指針返回。通過引用返回可以做到這樣的事情:

layer.getChannel().clear(); 

並讓它對該層中的通道起作用。

返回一個指針類似於返回一個引用,只不過它給了你更多的靈活性,因爲指針可以指向任何對象。當我希望能夠在另一個班級中使用「頻道」時,我經常使用指針。然後我會做

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

即使使用指針返回版本,也無法停止調用者創建新實例。

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

我知道有一種方法可以實現這個目標。 (例如,將Channle的ctor私有化,只有靜態成員函數或它的朋友函數才能創建它)。但是,我不認爲這是你問題的關鍵。

問題是,當你使成員函數返回引用或指針時,你給出一個調用者選項,他可以選擇是否要複製它或引用它。此外,您可以通過添加const使其更明確,使其只讀。

對於你的情況,我會去參考返回版本在通道不能爲空。如果你不想讓它們改變成員變量,則返回const引用。請記住,決定返回值類型沒有單一的最佳方式,因爲它取決於你想說的內容。希望能幫助到你! :)

1

既然你久違的對象,你給的類直接訪問對象的用戶,如果你要做到這一點,你爲什麼做對象私有的參考?只是公開。

+0

我試圖阻止任何其他對象設置Layer.channel。通過返回一個參考,我假設仍然可以設置對新通道的引用是否正確?我頭疼。 – ansiart 2011-04-24 04:47:01

-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. 

其他答案提示進行復制編譯錯誤是好的。

相關問題