2014-10-19 76 views
6

在很多情況下,我發現我的類需要私有函數來分解它們的功能並重用代碼。典型的實現將是:可以在.cpp中聲明/定義靜態方法嗎?

MyClass.h

#include "AnotherClass.h" 

class MyClass { 
public: 
    float foo() const; 
private: 
    float fooPrivate(const AnotherClass& ac) const; 
} 

MyClass.cpp

#include "MyClass.h" 

float MyClass::foo() const { 
    return fooPrivate(AnotherClass()); 
} 
float MyClass::fooPrivate(const AnotherClass& ac) const { 
    return ac.foo(); 
} 

這是確定的,但在頭文件中聲明fooPrivate()可在下列情況下存在問題:

  • 我們可能不希望AnotherClass包含在頭文件中,如果它只是供內部使用,MyClass以外不需要。

  • 如果需要很多私有函數,我們可能會用不必要的私有函數來污染頭文件,這會使代碼不清晰,增加編譯時間並且更難以維護。

我知道PIMPL方法,解決了所有這些問題,但我的問題是,如果我們不希望使用平普爾是否確定了幾個功能做這樣的事情?

MyClass.h

class MyClass { 
public: 
    float foo() const; 
} 

MyClass.cpp

#include "MyClass.h" 
#include "AnotherClass.h" 

static float fooPrivate(const AnotherClass& ac) { 
    return ac.foo(); 
} 
float MyClass::foo() const { 
    return fooPrivate(AnotherClass()); 
} 

在這種情況下,不需要它包括AnotherClass.h在MyClass.h和fooPrivate()不能被任何人稱爲除了MyClass.cpp內部和聲明之後。我對嗎?

是否有任何使用此警告的注意事項,或者當我的程序變得更大時,我是否會遇到問題?

+0

在我看來,你的私人成員函數'fooPrivate'本來可以是靜態的。否則,你的第二種方法就不能很好地工作。 – 2014-10-19 14:52:39

+0

你知道,'AnotherClass'的前向聲明就足夠了。這足夠輕量。 – Deduplicator 2014-10-19 14:54:04

+0

我瞭解你。然而,這一點仍然是一樣的。即使fooPrivate()使用MyClass的某些成員(這會使其成爲非靜態的),但在很多情況下,可以使用靜態函數來執行某些內容,然後可以使用靜態調用的結果來修改此類。 – 2014-10-19 14:57:36

回答

11

實際上,它不僅是好的,我真的會推薦它。

private功能可以被使用,有時必須(訪問私有元素時),但是這裏有一個問題與他們同在,即使它只是一個聲明,他們雜亂的類定義:一個用戶班級不應該關心或暴露於班級內部。

另一方面,static函數或函數在源文件中的匿名名稱空間中聲明是「空閒」的。不管其中有多少你有:

  • 它們不會堆積頭
  • Itanium ABI編譯器工具鏈(例如),他們不會導致導出的符號,加快加載時間

但是,如果存在一個缺點,那就是在那些相同的與安騰相關的工具鏈上,它們缺少名稱會導致沒有調試符號的錯誤回溯。儘管如此,這可能會被視爲一個小麻煩。

注意:不能直接訪問private類的成員很少是一個問題,因爲類的方法可以很容易地將對這些成員的引用傳遞給它們。這意味着當構造函數不公開時,它們不能構建類的實例。

+1

+1的調試評論!這是迄今爲止最明確的答案。謝謝你的時間。 – 2014-10-19 15:14:12

+0

你在談論哪些與itanium相關的工具鏈? Itanium本身現在完全不相關,不是嗎? – 2017-09-11 10:27:25

+1

@avl_sweden:我正在談論(令人困惑的)[Itanium ABI](https://itanium-cxx-abi.github.io/cxx-abi/),這是Clang,GCC,ICC使用的ABI。 .. – 2017-09-11 12:02:23

6

除了輕微的不便之外,沒有任何警告。顯然,你的靜態函數不會是一個類方法。因此,它只能訪問公共類成員和方法。

3

由於你的幫助函數只使用類的公共接口,所以只能使用類實現文件中提供的靜態函數。

無論如何,你的例子並不真正需要的AnotherClass的定義,輕便的前瞻性聲明,會被罰款:

class AnotherClass; 

另外,我將標誌着功能inline在一般原則這兩種情況下,當且僅當它僅在實現中使用,並且全部位於同一個翻譯單元中:
性能更好/代碼更小,並且沒有任何缺點的可能性很小。

+1

+1對於'inline' – 2014-10-19 15:02:05

4

我偶爾會這樣做,因爲「幫助函數」在類的公共接口中幾乎沒有任何用處。我嘗試儘量減少使用這種模式,因爲沒有訪問private變量。但是,免費功能是好的 thing和arguably,甚至increase encapsulation

相關問題