13

擁有一個自由函數(匿名命名空間且只能在單個源文件中可訪問)並將所有變量作爲參數發送,而不是使私有類成員函數不帶任何參數和直接訪問成員變量?謝謝!自由函數與成員函數

頭:

Class A { 
    int myVariable; 
    void DoSomething() { 
     myVariable = 1; 
    } 
}; 

來源:

namespace { 
    void DoSomething2(int &a) { 
     a = 1; 
    } 
} 

int A::SomeFunction() { 
    DoSomething2(myVariable); // calling free function 
    DoSomething(); // calling member fucntion 
} 

如果你更喜歡讓他們的成員又是什麼,如果我有,我第一次調用不訪問任何成員變量的函數的情況下,但函數調用正在訪問成員的另一個函數。他們都應該成爲會員還是免費的?

+1

你至少可以編寫*試圖編譯的代碼嗎? – Shoe

+0

@StephaneRolland不,關於公共接口的鏈接,不是關於執行 – TemplateRex

+1

@TemplateRex讓我堅持,是關於使用成員函數還是不使用。讓我引用這樣一個答案:「有很多很多方法直接取決於班級的內部,最輕微的變化意味着整個重寫,不一定是這樣。」 –

回答

5

看到這樣一個問題:Effective C++ Item 23 Prefer non-member non-friend functions to member functionsC++ Member Functions vs Free Functions

你應該更喜歡免費的功能,在某種程度上,它促進了鬆散耦合。

考慮讓它成爲一個成員函數,只有當它的作用對你的班級的膽量,並且你認爲它確實與你的班級真正綁定。

這是本書的一個要點101 C++編碼標準,其中規定優先於成員函數的自由函數和靜態函數。

雖然這可能被認爲是基於意見,它可以保持課堂少,並分開關注。

answer陳述:「這個規則的原因是,通過使用成員函數,你可能過分依賴於一個班的內部意外。」

+0

是不是成員函數的問題,他們沒有保持其中的任何變量或指針的狀態?我的意思是,當自由函數終止時,在成員函數中聲明的指針和變量也是如此...... –

+1

不知道我明白你的意思。我會按照這種方式來糾正和重複你的句子:自由函數和方法之間沒有多少區別。我們可以簡化並且說方法只需訪問另一個稱爲'this'的輸入參數,並且該參數是隱式傳遞的,並且可以在方法內部訪問。一個方法具有** ABSOLUTELY **與關於局部變量和指針的生命範圍的自由函數沒有不同的行爲。 –

9

源文件中非成員函數的一個優點類似於Pimpl idiom的好處:如果更改實現,則使用頭的客戶端不必重新編譯。

// widget.h 
class Widget 
{ 
public: 
    void meh(); 
private: 
    int bla_; 
}; 

// widget.cpp 
namespace { 
    void helper(Widget* w) // clients will never know about this 
    { /* yadayada */ } 
} 

void widget::meh() 
{ helper(this); } 

當然,當這樣寫的,helper()只能使用Widget公共接口,所以您將獲得小。您可以在Widget內部輸入friendhelper()聲明,但在某些時候,您最好轉換成一個完整的Pimpl解決方案。

4

自由函數與成員函數的主要優點是它有助於將接口從實現中分離出來。例如,std::sort不需要知道什麼關於它在其上運行的底層容器,只是它允許訪問提供某些特性的容器(通過迭代器)。

在您的示例中,DoSomething2方法對於減少耦合沒有太大作用,因爲它仍然需要通過引用傳遞來訪問私有成員。相反,只是在簡單的DoSomething方法中進行狀態突變幾乎肯定會更明顯。

當你可以用一個類的公共接口來實現一個任務或算法時,那麼這使得它成爲一個免費函數的好候選者。Scott Meyers在這裏總結了一組合理的規則:http://cpptips.com/nmemfunc_encap