听起来您需要(运行时)多态性,即想要在IMyInterface
不知道其精确类型的情况下处理 an 的代码。单独的模板不会让你到达那里,因为它们只提供编译时多态性。提供您想要的 C++ 部分是 RTTI(运行时类型信息)和虚函数。C++ 极其强大的特性之一是您可以将这两种方法结合起来。在您的情况下,这意味着IMyInterface
变成模板,但让该模板继承自定义您需要的虚函数的非模板基类。这是一个例子。
// Base class for interface types. Make sure it's a polymorphic type by adding a least one
// virtual member. Since polymorphich types should have virtual destructory anyway, adding
// a virtual no-op destructor is the natural choice.
struct IMyInterfaceDataType {
virtual ~IMyInterfaceDataType() {};
};
// Base class for interface implementations.
struct IMyInterface {
virtual bool IsMyType(const IMyInterfaceDataType& data);
virtual void DoThings(IMyInterfaceDataType& data);
}
template<typename RequestType, typename ResponseType>
struct IMyInterfaceImplementation : MyInterface {
struct MyType : IMyInterfaceDataType {
union { RequestType Request; ResponseType Response } data;
// You'll probably want to add some constructors here
};
virtual bool IsMyType(const IMyInterfaceDataType& data) {
// Cast as pointer, not reference, to get NULL instead of an exception if cast fails
return dynamic_cast<const MyType*>(&data) != NULL;
}
};
struct SomeRequestType { ... };
struct SomeResponseType { ... };
struct SomeInterface : IMyInterfaceImplementation<SomeRequestType, SomeResponseType> {
virtual void DoThings(IMyInterfaceDataType& data_raw) {
// Throws std::bad_cast if data_raw isn't actually a DataType instance
DataType& data = dynamic_cast<DataType&>(data_row);
... Do whatever you want to do with data ...
}
};
// This should now work, but you need to store pointers (or references, but
// putting references into a std::vector doesn't work), since polymorphism only
// works as expected with references or pointers.
std::vector<IMyInterface*> interfaces;
void addCollection(IMyInterface* iface) {
interfaces.push_back(iface);
}
// This would then process an arbitrary data type with the first matching interface
void process(IMyInterfaceDataType& data) {
for(std::vector<IMyInterface>::iterator i = interfaces.begin(); i != interfaces.end(); ++i) {
IMyInterface& iface = **i;
if (iface.IsMyType(data) {
iface.DoThings(data);
break;
}
}
}
在实际代码中,您当然不应该在向量中存储原始点interfaces
,而是使用某种智能指针。boost::shared_ptr
(或者std::shared_ptr
如果您使用的是 C++11)将是一个不错的选择。您可能还想看看boost::any
,它以安全的方式包装了任意类型的对象(即,在某种程度上,它void*
是正确的)。
顺便说一句,您的使用union
有点可疑。方法如何DoThings
知道数据是包含请求还是响应?您可能要考虑使用boost::variant
而不是 C 风格的联合。