2011-06-04 52 views
4

想象一下這個簡單的基類:強制派生類重寫至少一個虛函數

struct simple_http_service 
{ 
    virtual reply http_get(…); 
    virtual reply http_post(…); 
    virtual reply http_delete(…); 
    // etc. 
}; 

我想防止用戶從此類派生沒有覆蓋的至少其中之一,並防止他們instantiang simple_http_service

是否有一些不錯方式做到這一點?

+0

我90%肯定沒有這樣做的一個非常好的方法,尤其是很難表達的約束類似於C++ – 2011-06-04 09:33:11

+2

呃做這些中的一個,似乎是靠不住的設計。如果他們忽略了三種功能中的兩種功能,還有什麼? – GManNickG 2011-06-04 09:37:09

+2

如果您提供了所有這些功能的良好默認實現,那麼如果有人想要派生出一個全部使用它們的類,那麼爲什麼它對您很重要? – 2011-06-04 09:40:06

回答

5

這聽起來像一個非常奇怪的約束。通過一切手段保護用戶免受不正確使用,但不要試圖禁止的東西,你只是「看不到的地步」。如果有,從你的類派生沒有覆蓋所有的三個功能是沒有意義的,然後讓他喜歡的用戶覆蓋儘可能多或儘可能少的功能,並相信他不會做得出的,無關緊要的事情,而不覆蓋任何的功能。用戶這樣做並沒有什麼壞處,但它不是很有用。

但是,如果你需要強制執行(再次,我建議你重新考慮),那麼不要使用虛擬功能。而是傳遞函數指針或函數對象(或std::function/boost::function)回調函數。讓基類是這個樣子:

struct simple_http_service 
{ 
    typedef std::function<reply (...)> func_type; 
    reply http_get(...) { return get_func(...); } 
    reply http_post(...) { return post_func(...); } 
    reply http_delete(...) { return delete_func(...); } 
    // etc. 

private: 
    func_type get_func; 
    func_type post_func; 
    func_type delete_func; 
}; 

現在只需添加必要的構造函數(或免費/靜態功能,所以你可以爲它們命名,以避免歧義),這樣的類只能當至少一個實例提供函數對象。

+0

我必須承認你是對的:) – 2011-06-04 10:14:10

+4

+1這是一個非常好的方法,很多人在第一遍中都沒有把握。我使用它,我推薦它。對於偶然的讀者來說:這意味着你不會*實現*不同的服務,而是*單一的服務,並且在構建過程中你可以將它設置爲派發到操作的句柄。您可以提供不同的* service *實例,它們將通過使用'std :: bind'來控制調度,或者可以將調度到單獨的* service *中的不同類,派發到基礎模型中相同類中的不同操作方法比繼承更靈活 – 2011-06-04 10:17:38

0

如果知道你想要的派生類覆蓋的方法,只需聲明方法pure virtual

例如,使HTTP_GET純虛:

struct simple_http_service 
{ 
    virtual reply http_get(…) = 0; 
    virtual reply http_post(…); 
    virtual reply http_delete(…); 
    // etc. 
}; 
+0

這正是我的問題 - 我不知道哪個會被重寫,但我想強制重寫至少一個。 – 2011-06-04 09:37:37

+0

@Karl:「但我想強制重寫至少一個」爲什麼? – GManNickG 2011-06-04 09:38:39

+0

@GMan因爲我不希望它有可能實例化基類。我想我會編輯這個問題... – 2011-06-04 09:40:41

1

我認爲所有的這些功能應該是純虛函數。你發佈的結構實際上是一個接口。如果函數並非都是必需的,派生的結構只應該爲與它們無關的函數提供一個空的實現。

1

如果你只是想執行的基類是抽象的,給它一個純虛析構函數,使您的多種功能的普通虛擬的。