2013-07-25 58 views
0

我想在下面的代碼中實現「這一行」。最合理的方法是設置GetDog靜態,但是我不能使用「this」。有沒有辦法避開它? (不,因爲我想出來,有幾行的問題不相關)不聲明類的調用函數

#include <iostream> 

class Dog 
{ 
public: 
    static int a; 
    Dog& GetDog(int k) 
    { 
     this->a = k; 
     return *this; 
    } 
    int bark() 
    { 
     return a*a; 
    } 
}; 

int Dog::a=0; 

int main() 
{ 
    Dog puppy; 
    int i = puppy.GetDog(4).bark(); 
    cout<<i<<endl; 
    cout<<Dog::a<<endl; 
    //i = Dog::GetDog(6).bark();     //this line 
    return 0; 
} 

不,這樣做有很大的優勢(僅僅是聲明一個類是不要求),但我看到它在使用我正在使用一些軟件包。我有點想了解它是如何完成的。

class EXOFastFourierTransformFFTW 
{ 
    public: 
    static EXOFastFourierTransformFFTW& GetFFT(size_t length); 
    virtual void PerformFFT(const EXODoubleWaveform& aWaveform, EXOWaveformFT& aWaveformFT); 
... 
int main() 
{ 
    EXODoubleWaveform doublewf; 
    EXOWaveformFT wfFT; 
    ... 
    EXOFastFourierTransformFFTW::GetFFT(doublewf.GetLength()).PerformFFT(doublewf,wfFT); 
... 

這個靜態函數的用法也出現在GEANT4,這可能是由物理學家寫的,所以他們可能不會做最聰明的事情編程。我仍然想要如果這樣做有其他優點,但。

從投票下來之前,我可以看到,這可能不是一個正常的方法,因爲我認爲它是。在做之前請評論。

+2

你的標題說,C(爲什麼),但你標記它的C++和使用C++。 – chris

+0

函數名稱中的'C:'的含義 –

+0

你究竟在問什麼?你認爲哪個班沒有申報? 'EXOFastFourierTransformFFTW'是提供的代碼中聲明的類,但它不是_instantiated_類。運行時不存在「EXOFastFourierTransformFFTW」類型的對象,這非常好,因爲您不需要該類型的對象來調用靜態函數'GetFFT'。這一切都檢查出來,但涉及到我的部分是調用代碼忽略從'GetFFT'返回的'EXOFastFourierTransformFFTW&'。忽略返回的引用是不好的mojo .... – Shaz

回答

0

看來它是Meyers單身人士的執行。

我解釋一下:

在給出的例子中,類EXOFastFourierTransformFFTW似乎並不有一個構造函數,但返回參照EXOFastFourierTransformFFTW對象。

而且它看起來像這樣實現:

class Singleton 
{ 
public: 
    static Singleton& Instance() 
    { 
     static Singleton obj; 
     return obj; 
    } 

private: 
    Singleton(); 
}; 

this book from Andrei Alexandrescu,它是說:

這種簡單和優雅的實現首先是由斯科特邁爾斯公佈;因此,我們將其稱爲Meyers Singleton。 Meyer的單身人士依靠一些編譯器的魔力。當控制流首次通過它的定義時,函數靜態對象被初始化。不要混淆在運行時初始化靜態變量[...]

[...]

此外,編譯器,初始化完成後,運行時支持註冊銷燬變量生成代碼。

因此,良好的使用靜態從不會被實例類調用一個方法,但不這樣做,如果它是沒有必要的......在這裏代表一個Singleton模式你要。

但是現在,如果你想你的類Dog看起來像:

class Dog 
{ 
public: 
    static Dog& GetDog(int k) 
    { 
     static Dog obj(k); 
     return obj; 
    } 
    int bark() 
    { 
     return a*a; 
    } 
private: 
    int a; 
    Dog(int iA) : a(iA) {} 
}; 
+0

由於'Get'函數有參數,這有點複雜。我可能不希望'GetDog(1)'和'GetDog(2)'引用同一個對象... – aschepler

+0

@aschepler如果你看一下web上的這個例子(https://gist.github。 com/mgmarino/3816940),我仍然認爲'EXOFastFourierTransformFFTW'是一個單例(至少它看起來像...)。將參數傳遞給'GetFFT'並不是一個好主意,即使是理解的一個壞主意,但是... –

+0

我覺得參考在PerformFFT後被刪除,但我不確定是否有可能。 – Rabbitybunny

0

static函數的用法是正確的 - 它允許您在沒有類的實例的情況下使用類的函數。您給出的FFT示例可能會在靜態函數中創建一個實例。所以在你的情況下,你可以在GetDog函數中實例化Dog(只需要注意返回對局部變量的引用!)。

+0

如果靜態函數創建了一個實例,通過引用返回可能是一件壞事... –

+0

這就是爲什麼我提到要小心返回引用 - 如果你通過'new'實例化,我想你可以逃脫它 –

+0

的確,但是誰刪除它,什麼時候? 'T&t = T :: getT(42); ...;刪除&t;'不是令人愉快的代碼... –

0

你說你不能使用this如果你使它static,這是真的。但是如果你將來需要使用this,你爲什麼要在不使用Object實例的情況下訪問它?如果它有一個默認值或類似的東西,你可以在函數的其他地方聲明public static,然後以這種方式訪問​​它。如果你澄清了一些你正在做的事情,我會相應地編輯/刪除這個答案。

+0

我認爲案例是,「代碼編寫器」不希望太多的類聲明(我認爲是「實例」),如果這樣的類完全像全局函數一樣工作。而且由於FFTW來自外部封裝,「公共靜態」可能並不理想。 (我覺得他們可能會使用命名空間,但我不熟悉這一點) – Rabbitybunny

+0

@Rabbitybunny命名空間也可以工作,我想。我不是C/C++方面的專家,但是我認爲我會投入我的兩分錢來解決問題。 –

+0

是的,但FFTW函數包「實現」,因此不使用名稱空間以及全局靜態。因此,我試圖找出函數中的「這個」問題。我試圖在函數中聲明Dog類變量,但無法讓它工作。 – Rabbitybunny