【发布时间】:2012-02-19 14:06:20
【问题描述】:
在 C++ 中,假设以下类层次结构:
class BaseClass { };
class ChildClass : public BaseClass { };
进一步假设这两个类的工厂类具有一个通用的模板化基类:
template<typename T>
class Factory {
public:
virtual T* create() = 0;
};
class BaseClassFactory : public Factory<BaseClass> {
public:
virtual BaseClass* create() {
return new BaseClass(&m_field);
}
private:
SomeClass m_field;
};
class ChildClassFactory : public Factory<ChildClass> {
public:
virtual ChildClass* create() {
return new ChildClass(&m_field);
}
private:
SomeOtherClass m_field; // Different class than SomeClass
};
请注意,ChildClassFactory 和 BaseClassFactory 的大小/内部结构因字段不同而不同。
现在,如果有ChildClassFactory(或Factory<ChildClass>)的实例,我可以安全地将其转换为Factory<BaseClass>(通过reinterpret_cast)吗?
Factory<ChildClass>* childFactory = new ChildClassFactory();
// static_cast doesn't work - need to use reinterpret_cast
Factory<BaseClass>* baseFactory = reinterpret_cast<Factory<BaseClass>*>(childFactory);
// Does this work correctly? (i.e. is "cls" of type "ChildClass"?)
BaseClass* cls = baseFactory->create();
我知道您不能总是以这种方式转换模板类,但在这种特殊情况下,转换应该是安全的,不是吗?
我已经用 Visual C++ 2010 对其进行了测试,它确实可以工作。我现在的问题是这是否可以移植到其他编译器?
更新:由于存在一些混淆,让我再澄清一下在我的示例中什么(应该是)重要的:
-
ChildClass是BaseClass的子类 -
Factory<BaseClass>的用户不知道将创建BaseClass的哪个子类。他只知道BaseClass已创建。 -
Factory<T>没有自己的字段(除了 vtable)。 -
Factory::create()是virtual
【问题讨论】:
-
在您的代码的这个特定片段中,我没有看到任何错误。
-
请注意,您的
BaseClassFactory和您的ChildClassFactory类在任何方面都没有任何关系。此外,拥有Factory<T>模板没有任何意义,因为每个模板实例都是不同的、不相关的类型,因此虚拟接口根本没有给您带来任何好处。 -
@SebastianKrysmanski C++ 代码发生工作并不意味着它不是完全错误的。而说它与Visual C++一起工作,就更没有意义了。
-
@SebastianKrysmanski:当我执行
T* t = new T; delete t; t->foo();之类的操作并且它目前适用于我当前的编译器时,这是否意味着“它不可能完全错误”? -
@SebastianKrysmanski:我的意思是您可以完全删除
Factory<T>模板,您将获得完全相同的行为。
标签: c++ templates casting virtual reinterpret-cast