2011-12-19 41 views
9

我有一個實現引用計數的C++類,我希望此類的所有用戶只能從這個類繼承,因此沒有任何對象會以多個引用計數器結束。如何檢測和斷言特定類的虛擬繼承?

我想在編譯時或至少在運行期間以某種方式來斷言這個需求。

有沒有辦法做到這一點?

回答

5

我認爲包裝課是最簡單的選擇。而不是直接從RefCounter繼承創建一箇中介類。

struct RefCounterVirtPrivate_ 
{ 
    int count; 

    RefCounterVirt() 
     : count(0) 
    { } 
}; 

struct RefCounter : public virtual RefCounterVirtPrivate_ 
{ 
}; 

struct A : public RefCounter { }; 
struct B : public RefCounter { }; 
struct C : public A, public B { }; 

然後,一切都可以從RefCounter繼承而不需要關心虛擬的傳承。你甚至不需要改變任何現有的代碼 - 虛擬繼承RefCounter本身應該是無害的。

這當然不能保證人們不會直接從RefCounterVirtPrivate_繼承,但這就是爲什麼我給它一個明顯的名字。意外地做到這一點比忘記virtual關鍵字更難。

0

它應該是可能的一些欺騙,但考慮其含義:你設置的政策,對象需要立即自毀,如果其參考計數器達到零。

根據您的應用程序,你可能要離開的確切時間時,它調用delete this;對象的實現,即只有在基類add_ref()release()抽象函數(這使得一個具體實施中出現所有的接口vtables都有適當的thunking)並且將維護引用計數的負擔放在具體的類上。

+0

實際上,這個類在任何時候都會自己刪除'',所以我可以在'addref()'/'release()'中進行檢查。所以詭計是受歡迎的。 – sharptooth 2011-12-19 10:04:36

9

像這樣的東西?

struct RefCounter { 
    template <typename T> 
    RefCounter(T *) { 
     BOOST_STATIC_ASSERT(boost::is_virtual_base_of<RefCounter, T>); 
    } 
}; 

struct GoodClass : virtual RefCounter { 
    GoodClass() : RefCounter(this) {} 
}; 

struct BadClass : RefCounter { 
    BadClass() : RefCounter(this) {} 
}; 

這是一個關於需要通過this的構造,雖然捕捉到派生類型的恥辱。當然,一個狡猾的用戶可以通過傳遞this以外的東西來顛覆它。

+0

您可以使用CRTP而不是'this',但我認爲您的解決方案更好。 – sbi 2011-12-19 10:05:49

+0

@sbi:我認爲,但是'RefCounter '和'RefCounter '將是不同的類,所以即使它們是虛擬的,您仍然可能會得到多個refcounter基類子對象。 – 2011-12-19 10:07:54

+0

如果一個類繼承兩個基地,一個基地從'RefCounter'虛擬繼承,另一個基地繼承非虛擬? – sharptooth 2011-12-19 10:09:08