2011-06-15 127 views
3

公共成員,我有一個基類,它看起來是這樣的:沒有繼承

class Base 
{ 
public: 
    typedef std::shared_ptr<Base> ptr_t; 
    typedef std::weak_ptr<Base> wptr_t; 

    enum class Type { foo, bar, baz }; 

    Type x; 
    // ... 
}; 

我想那些內部類型是公共的,這樣我可以做的東西一樣Base::ptr_t my_ptr(new Base);等。但是,如果我做一個新的類像這樣...

class Derived : public Base 
{ 
    // ... 
}; 

不幸的是,Derived::ptr_t仍然是一個基本指針。我希望Derived從Base公開繼承x,但不繼承ptr_t,wptr_tType。例如

Derived a; 
a.x = Base::Type::foo; // this should work 
a.x = Derived::Type::foo; // but I want this to fail 

這是可能的,但也許一些魔術使用friendvirtual或類似的東西?

+0

既然你想讓指針類型匹配類的類型,我不禁想着你應該使用模板而不是繼承。 – MatthewD 2011-06-15 03:17:48

+0

我希望指針類型匹配類的類型,但我也希望基類型存在,以便它可以用作基類型。如果有一個模板能夠自動獲得派生類型的指針typedefs,但是我還沒有想到用模板實現這個功能的簡單方法 - 所以我會滿足於將它們完全禁用(這基本上是這個問題的關鍵)。 – karadoc 2011-06-15 03:47:20

回答

0

基於iammilind和呂克·丹東的答案,這就是我已經拿出:

class Base 
{ 
private: 
    // only 'BaseClass' is allowed to derive from Base 
    Base() { } 
    friend class BaseClass; 
public: 
    typedef std::shared_ptr<Base> ptr_t; 
    typedef std::weak_ptr<Base> wptr_t; 

    enum class Type { foo, bar, baz }; 

    Type x; 
    // ... 
}; 

class BaseClass : public Base 
{ 
private: 
    // make all the raw_Base types private 
    using Base::ptr_t; 
    using Base::wptr_t; 
    using Base::Type; 
}; 

class Derived : public BaseClass 
{ 
    // define as usual, and now all is well in the world. 
}; 

// now, to test it 
class Derived2 : public Base { }; // fails 

Derived d; 
d.x = Derived::Type::foo; // fails 
d.x = Base::Type::foo; // works 
// Which is exactly what I wanted. 

作爲就我所知,這個解決方案的唯一問題是它增加了一個新的,可能令人困惑的類。這個類被定義爲不會被真正誤用 - Base本身不能從BaseClass除外,但仍然是BaseClass是一個沒有吸引力的命名空間混亂。

但是,對於我打算使用此代碼的特定代碼,我碰巧已經使用相當於BaseClass來解決無關的問題。所以這個技術很適合我的目的。

4

只需覆蓋類型:

class Derived { 
    typedef int Type; 
}; 

它將not allow the use ofDerived::Type(因爲它是私有的,以及typedef ED)

+0

這是一個好主意,但不是將它寫入派生類的每一個風格,我最終可能會做的是這樣的: 'class SafeBase:public Base { {typedef void ptr_t; typedef void類型; //等' 然後派生自SafeBase而不是從Base。 – karadoc 2011-06-15 03:50:23

+0

@卡拉多克,是的,這是一個好主意。我的解決方案只是實現目標的一種方式。現在根據需要你可以使用它。你也可以考慮受保護的繼承(如果你不想'typedef')。 (例如'class Derived:protected Base' – iammilind 2011-06-15 03:55:08

+0

OP從'Base'派生'Derived'時使用公共繼承的事實可能表明OP想要在派生和Base之間有IS-A關係。無關的'SafeBase'也不保護繼承符合這個意圖 – AnT 2011-06-15 04:36:39

3
class Derived : public Base 
{ 
    // This is now private 
    using Base::ptr_t; 
    using Base::wptr_t; 
    // ... 
}; 
+0

我認爲這不是問題,OP希望'Base :: Type'不能作爲Derived :: Type在任何地方使用(儘管它是合法的)。 – iammilind 2011-06-15 03:48:08

+0

@iammilind OP中的示例僅包含公共使用。 – 2011-06-15 03:54:43