2011-05-04 64 views
0

我有一堆容器和對象。容器和對象具有模板化的子類。那些模板化的子類有專門的子類。在專門的對象中,我想檢索它們的容器。下面的代碼設置:返回模板子類

class Container; 
template<class T> class SubContainer; 

class Object 
{ 
public: 
    Object() : m_pContainer(NULL) { } 

public: 
    Container* GetContainer() 
    { 
    return m_pContainer; 
    } 

    void SetContainer(Container* pContainer) 
    { 
    m_pContainer = pContainer; 
    } 

private: 
    Container* m_pContainer; 
}; 

class Container 
{ 
public: 
    Container() : m_pObject(NULL) { } 
    virtual ~Container() { } 

public: 
    void SetObject(Object* pObject) 
    { 
    m_pObject = pObject; 
    m_pObject->SetContainer(this); 
    } 

protected: 
    Object* m_pObject; 
}; 

template<class T> 
class SubObject : public Object 
{ 
public: 
    virtual SubContainer<SubObject>* GetSubContainer() 
    { 
    return dynamic_cast<SubContainer<SubObject>*>(GetContainer()); 
    } 

    void TestMe() 
    { 
    SubContainer<SubObject>* pSubContainer = GetSubContainer(); 
    assert(pSubContainer); 
    } 
}; 

template<class T> 
class SubContainer : public Container 
{ 
}; 


class SubObjectInt : public SubObject<int> 
{ 
}; 

class SubContainerSubObjectInt : public SubContainer<SubObject<int> > // works 
//class SubContainerSubObjectInt : public SubContainer<SubObjectInt> // fails 
{ 
}; 

測試代碼:

SubContainerSubObjectInt* pContainer = new SubContainerSubObjectInt(); 
SubObjectInt* pObject = new SubObjectInt(); 

pContainer->SetObject(pObject); 

pObject->TestMe(); 

我知道SubContainer<SubObjectInt>不是SubContainer<SubObject<int> >即使SubObjectInt是一個子類SubObject<int>一個子類。

我標記了代碼「工作」和「失敗」。說「失敗」的行在我的代碼中更具邏輯意義,但我無法檢索到保存它的適當的子容器。動態轉換總是返回NULL。

我的問題是:我如何檢索正確的SubContainerGetSubContainer()SubObject

我希望這是有道理的。

回答

0

你可以嘗試的東西沿着這條:

class SubObjectInt : public SubObject<int> 
{ 
    public: 
    typedef SubObject<int> parent; 
}; 

class SubContainerSubObjectInt 
: virtual public SubContainer<SubObjectInt> 
, virtual public SubContainer<SubObjectInt::parent> 
{ 
    public: 
    void SetObject(Object* pObject) 
    { 
    SubContainer<SubObjectInt::parent>::SetObject(pObject); 
    } 
}; 

更清潔,你應該私下從子容器繼承並重新發布,你需要爲公共成員的實際方法。

2

你的代碼的最小變化將發生變化:

class SubObjectInt : public SubObject<int> 
{ 
}; 

typedef SubObject<int> SubObjectInt; 

當前失敗的定義現在可以編譯並返回一個有效的指針。

如果你想具體的代碼具體到SubObjectInt是從子對象不同,那麼你可以代替有:

template<class T> 
class SubObject : public Object 
{ 
public: 
    typedef SubContainer<SubObject<T> > ContainerType; 

    ContainerType* GetSubContainer() 
    { 
     Container* container = GetContainer(); 
     return dynamic_cast<ContainerType*>(container); 
    } 

    void TestMe() 
    { 
     ContainerType* pSubContainer = GetSubContainer(); 
     assert(pSubContainer); 
    } 
}; 

然後你的測試代碼如下所示:

SubObjectInt::ContainerType* pContainer = new SubObjectInt::ContainerType(); 
SubObjectInt* pObject = new SubObjectInt(); 

pContainer->SetObject(pObject); 

pObject->TestMe(); 

編輯:迴應第一條評論

嗯,我會說你可能會更好使用不同的設計,你是混合繼承和組成和溫度這種方式會使我想要達到的目標複雜化。

您有一個您希望能夠分配對象的容器類型。 你有一個想知道它的容器的對象類型。

你想要的容器和對象類型,做一些事情相同,並根據其內容有所不同。

我建議這些方針:對象或容器的

template<class T> 
class ObjectStrategy 
{ 
public: 
    virtual void execute(T* object) 
    { 
     std::cout << "oh noes i am a default general ObjectStrategy" << std::endl; 
    } 
}; 

template<class T> 
class ContainerStrategy 
{ 
public: 
    virtual void execute(T* container) 
    { 
     std::cout << "oops i am a default general ContainerStrategy" << std::endl; 
    } 
}; 

template<class T> 
class Object; 

template<class T> 
class Container 
{ 
public: 
    Container() : m_pObject(0), m_strategy(new ContainerStrategy<Container<T> >()) { } 
    Container(ContainerStrategy<Container<T> >* strategy_override) : m_pObject(0), m_strategy(strategy_override) { } 
    ~Container() { delete m_strategy; } 

    void SetObject(T* pObject) 
    { 
     m_pObject = pObject; 
     m_pObject->SetContainer(this); 
    } 

    void DoContainerStuff() 
    { 
     m_strategy->execute(this); 
    } 

protected: 
    T* m_pObject; 
    ContainerStrategy<Container<T> >* m_strategy; 
}; 

template<class T> 
class Object 
{ 
public: 
    Object() : m_pContainer(0), m_strategy(new ObjectStrategy<Object<T> >()) { } 
    Object(ObjectStrategy<Object<T> >* strategy_override) : m_pContainer(0), m_strategy(strategy_override) { } 
    ~Object() { delete m_strategy; } 

    Container<Object<T> >* GetContainer() 
    { 
     return m_pContainer; 
    } 

    void SetContainer(Container<Object<T> >* pContainer) 
    { 
     m_pContainer = pContainer; 
    } 

    void DoObjectStuff() 
    { 
     m_strategy->execute(this); 
    } 

    void TestMe() 
    { 
     DoObjectStuff(); 
     Container<Object<T> >* pContainer = GetContainer(); 
     pContainer->DoContainerStuff(); 
    } 
protected: 
    Container<Object<T> >* m_pContainer; 
    ObjectStrategy<Object<T> >* m_strategy; 
}; 

typedef Object<int> ObjectInt; 

template<> 
class ObjectStrategy<ObjectInt> 
{ 
public: 
    virtual void execute(ObjectInt* container) 
    { 
     std::cout << "omg i am a default specific strategy for ObjectInt" << std::endl; 
    } 
}; 

typedef Container<ObjectInt> ContainerObjectInt; 

template<> 
class ContainerStrategy<ContainerObjectInt> 
{ 
public: 
    virtual void execute(ContainerObjectInt* container) 
    { 
     std::cout << "pow i am a default specific strategy for ContainerObjectInt" << std::endl; 
    } 
}; 

class ObjectIntOverrideStrategy : public ObjectStrategy<ObjectInt> 
{ 
public: 
    virtual void execute(ObjectInt* object) 
    { 
     std::cout << "bam i am an overriding specific strategy for ObjectInt" << std::endl; 
    } 
}; 

class ContainerObjectIntOverrideStrategy : public ContainerStrategy<ContainerObjectInt> 
{ 
public: 
    virtual void execute(ContainerObjectInt* object) 
    { 
     std::cout << "woo i am an overriding specific strategy ContainerObjectInt" << std::endl; 
    } 
}; 

int main(int argc, char** argv) 
{ 
    { // test with default + general strategies 
     typedef Object<float> ObjectFloat; 
     typedef Container<ObjectFloat> ContainerObjectFloat; 

     ObjectFloat* pObject = new ObjectFloat(); 
     ContainerObjectFloat* pContainer = new ContainerObjectFloat(); 

     pContainer->SetObject(pObject); 

     pObject->TestMe(); 
    } 

    { // test with default + specific strategies 
     ObjectInt* pObject = new ObjectInt; 
     ContainerObjectInt* pContainer = new ContainerObjectInt; 

     pContainer->SetObject(pObject); 

     pObject->TestMe(); 
    } 

    { // test with overriding + specific strategies 
     ObjectInt* pObject = new ObjectInt(new ObjectIntOverrideStrategy); 
     ContainerObjectInt* pContainer = new ContainerObjectInt(new ContainerObjectIntOverrideStrategy); 

     pContainer->SetObject(pObject); 

     pObject->TestMe(); 
    } 

    return 0; 
} 

通用功能被實現爲分別物體或容器的成員函數。

對象或容器的每種類型功能都是通過策略對象的組合來實現的,您可以使用工廠根據適當的策略生成適當的對象和容器。我提出了一個相當靈活的方法(可能太靈活了),所以你可以忽略策略對象上的模板特化或繼承,這取決於你需要的特定行爲。

+0

因此不可能將pContainer聲明爲SubContainerSubObjectInt?因爲所有專門的類都有代碼(我只是將它們設爲空白以儘可能簡化示例)。 – Ben 2011-05-05 17:23:54