2014-02-17 36 views
1

如何確保在編譯時調用特定的方法?在編譯時確保調用方法

例如,假設我有2種方法的對象:

struct Foo 
{ 
    ... func1(...); 
    ... func2(...); 
}; 

,我想確保FUNC1到FUNC2任何調用之前被調用,即:

int main() 
{ 
    Foo f; 
    ... 
    f.func1(...); 
    f.func2(...); 
    f.func2(...); // and so on 
} 

但我想生成編譯錯誤,如果我做這樣的事情:

int main() 
{ 
    Foo f; 
    ... 
    f.func2(...); // generate a compile error due the fact that func1 must be called first 
    f.func1(...); 
    f.func2(...); // and so on 
} 
+0

您可以嘗試使用'constexpr',但在這種情況下不起作用。 (不保證在任何情況下都能正常工作)。 –

+0

我想這隻能用代碼分析儀完成。編譯器本身只能警告你一個未使用的函數 - AFAIK。 –

+2

如果你需要這樣做,你應該不斷思考一個更好的課堂設計。這是一個順序耦合反模式:http://en.wikipedia.org/wiki/Sequential_coupling –

回答

5

有沒有真正的方法來執行t他在彙編時。這是什麼,對象本身將需要運行時檢查執行

11

雖然好奇,爲什麼你會做到這一點,一般需要注意的是,你必須暴露給用戶不能使用錯誤的接口。膽量去私人:

struct Foo 
{ 
public: 
    void callme() 
    { 
     func1(); 
     func2(); 
    } 

private: 
    ... func1(...); 
    ... func2(...); 


}; 

int main() 
{ 
    Foo f; 
    f.callme(); 
} 

如果您需要強制執行的對象之一時初始化,這樣做在構造函數中:

struct Foo 
{ 
public: 
    Foo() 
    { 
     func1(); 
    } 

    func2(...); 
private: 
    ... func1(...); 
}; 

int main() 
{ 
    Foo f; // func1() called automagically 
    f.func2(); 
} 

設計類接口,您必須八方通去想最糟糕的事情:用戶從來不看文檔中,用戶總是忘記調用foo.initialize(),用戶總是忘記釋放內存並泄漏等。

+0

我還提到,你可以通過使用'std :: forward將'callme'參數傳遞給'func1 ... funcn' '。有足夠的決心,你可以從它應該使用的函數列表中自動創建'callme'的簽名,使它更加透明。 –

+0

你問我爲什麼要這樣。看看這篇文章(http://www.di.unipi.it/~nids/docs/templates_vs_inheritance.html)。在這裏,當你使用模板做一個策略模式(不確定它是否是一個策略模式)時,你不是通過構造函數初始化對象,而是調用一個init函數。我想確保用戶已完成此操作,但是在編譯時。 – Amadeus

+0

@TomásBadan在這個例子中,我沒有在'init()'方法中看到任何需要。事實上,他們*可以被構造函數替換。因此,無論以前誰調用init(),現在都只是將參數傳遞給構造函數或工廠(將它們傳遞給構造函數)。 – Drop

3

想到的一種方法是讓func1()返回一個對象,它像func2() :

class Foo { 
public: 
    Proxy func1(); 
private: 
    void func2(); 
    friend class Proxy; 
}; 

class Proxy { 
private: 
    explicit Proxy(Foo& f) : f_(f) {} 
public: 
    void func2() { 
     f_.func2(); 
    } 
    friend class Foo; 
}; 

Foo f; 
f.func1().func2(); 

的另一種方法(我的最愛),就是讓FUNC1()是一個構造函數或使用的其他類,在它的構造函數調用FUNC1():

class Foo 
{ 
private: 
    void func1(), func2(); 
    friend class FooUser; 
}; 

class FooUser 
{ 
public: 
    explicit Proxy(FooUser& f) : f_(f) { 
     f.func1(); 
    } 

    void func2() { 
     f_.func2(); 
    } 
}; 
1

編譯器可以不會強制執行函數調用的順序,因爲通常只能在運行時確定。但是它可以在對象可以使用之前強制執行對象初始化。因此,獲得編譯時檢查的最佳方法是在構造函數中執行任何func1的操作 - 無論是Foo的構造函數的一部分,還是需要創建的幫助對象,才能調用func2

1

我真的不建議這樣做,但如果您需要它進行調試,您可以嘗試以下操作。 每次調用func1的()更改爲

#define FLAG 
func1(); 

和FUNC2()來

#ifdef FLAG 
func2(); 
#else 
#error func1 should be called first! 
#endif 

那麼您將收到一個編譯時錯誤,如果FUNC2()將在上文中提到然後FUNC1。這並不意味着它會在執行過程中更早被調用。

相關問題