我有一堆容器和对象。容器和对象具有模板化的子类。那些模板化的子类具有专门的子类。在专门的对象中,我想要检索它们的容器。这是代码设置:
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。
我的问题是:如何在SubContainer
中使用GetSubContainer()
检索正确的SubObject
?
我希望这是有道理的。
答案 0 :(得分:2)
对代码的最小更改将会改变:
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;
}
对象或容器的常用功能分别实现为对象或容器的成员函数。
对象或容器的每种类型功能是通过策略对象的组合实现的,您可以使用工厂根据适当的策略生成适当的对象和容器。
我提出了一种相当灵活的方法(可能过于灵活),因此您可以忽略策略对象的模板特化或继承,具体取决于您需要行为的具体方式。
答案 1 :(得分: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);
}
};
为了更清洁,您应该从SubContainer私下继承,并重新发布您作为公共成员所需的实际方法。