返回模板子类

returning template subclass

本文关键字:子类 返回      更新时间:2023-10-16

我有一堆容器和对象。 容器和对象具有模板化子类。 这些模板化子类具有专用子类。 在专用对象中,我想检索它们的容器。 下面是代码设置:

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> >的子类,即使SubObjectIntSubObject<int>的子类。

我将代码标记为"工作"和"失败"。 "失败"的行在我的代码中更合乎逻辑,但我无法检索保存它的正确子容器。 动态强制转换始终返回 NULL。

我的问题是:如何在SubObject中检索正确的GetSubContainer() SubContainer

我希望这是有道理的。

对代码的最小更改是更改:

class SubObjectInt : public SubObject<int>
{
};

typedef SubObject<int> SubObjectInt;

当前失败的定义现在将编译并返回有效的指针。

如果您希望特定代码特定于不同于 SubObject 的 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;
}
对象或容器

的通用功能分别作为对象或容器的成员函数实现。

对象或容器的

每种类型的功能是通过策略对象的组合来实现的,您可以使用工厂根据适当的策略生成适当的对象和容器。

我提出了一个相当灵活的方法(可能太灵活了),所以你可以忽略策略对象的模板专用化或继承,这取决于你需要行为的具体程度。

你可以尝试这样的事情:

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);
  }
};

为了更简洁,您应该私下从子容器继承,并将所需的实际方法重新发布为公共成员。