我有一个基类,Message
,它决定了政策。我还为特定的消息实例推导了该类。
考虑这个简化的例子:
template< ::size_t MessageSize >
struct Message {
enum { size = MessageSize };
Bits< ChunkSize > bits_[size / ChunkSize];
// Defines behavior for the Message types
};
template< ::size_t MessageSize >
struct SmallMessage : public Message< MessageSize > {
Bits< MessageSize > bits_;
};
// other derivations of Message...
template< class MessageType, ::size_t MessageSize >
struct MakeMessage {
typedef typename IfElseType<
MessageSize < ChunkSize,
SmallMessage< MessageSize >,
Message< MessageSize >
>::type type;
};
如果ChunkSize
为32,我会生成以下内容:
MakeMessage< FooMessage, 16 >
Message< 16 >
将导致Bits< 32 > bits_[0];
,而SmallMessage< 16 >
将包含Bits< 16 > bits_
,据我了解,这将遮蔽原始的零大小成员。
我知道有几种方法可以解决这个问题:
bits_
以外的名称,并提供覆盖该SmallMessage
以隐藏Message
处理bits_
本地实施的所有方法Message
虚拟我的问题是这两种方法是否有好处,或者是否有更好的方法为各种大小的内存容器提供接口,如上所述。
归根结底,我想要有以下几点:
typedef MakeMessage< FooMessage, 16 >::type message_type;
// ...
message_type message;
message.doSomethingToBits ();
无论实际使用什么容器,都要正常工作。
答案 0 :(得分:0)
好吧,尽管我可以通过大量的template
和typename
进行锻炼,但您尝试使用继承进行合成,这被认为是错误的方法。 SmallMessage
此处不类型为Message
,因为您注意到它不支持以相同方式处理bits_
数组。
我认为正确的方法是将Message
作为抽象基类(重要的是:没有 bits_
任何类型,可能是很多纯虚拟函数),然后SmallMessage
和BigMessage
作为实现。此外,由于您无论如何都在使用模板,因此类型是在编译时计算出来的,实际上根本没有理由可以使用Message
。只要SmallMessage
和BigMessage
具有相同的签名,即使它们没有公共基类,您也可以使用message_type
进行描述。您需要基类Message
的唯一原因是,如果您想使用后期绑定更一般地讨论消息。虽然拥有基类也将静态强制签名在声明中匹配,而不是给出奇怪的错误......有时......在代码的远端部分,因为你在其中一个类中错误地声明了一个方法(但不是其他)。
这是一个安全的赌注,你也希望BigMessage::bits_
是[(size-1) / ChunkSize + 1]
,这只是天花板而不是地板。这样你实际上有足够的Bits
es来适应你所有的位。