我有一个基类,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_
的名字并为此提供一个重写的接口(interface) - 修改
SmallMessage
隐藏Message
的所有方法处理bits_
与本地实现 - 制作
Message
中的方法虚拟
我的问题是这两种方法是否都有好处,或者是否有更好的方法来为各种大小的内存容器提供接口(interface),如上所述。
最终,我想要一些类似的东西:
typedef MakeMessage< FooMessage, 16 >::type message_type;
// ...
message_type message;
message.doSomethingToBits ();
不管实际使用的是什么容器,工作都是一样的。
最佳答案
好吧,尽我所能通过大量的 template
和 typename
,你正在尝试使用继承来组合,这被认为是错误的方式做吧。 SmallMessage
这里不是一种Message
,因为正如您所注意到的,它不支持处理bits_
以同样的方式排列。
我认为正确的方法是将 Message
作为抽象基类(重要:no bits_
任何类型的,可能有很多纯虚函数),然后是 SmallMessage
和 BigMessage
作为实现。此外,由于您无论如何都在使用模板,因此类型是在编译时确定的,实际上可能根本没有理由使用 Message
。只要 SmallMessage
和 BigMessage
具有相同的签名,即使它们没有共同的基类,您也可以按照您的描述使用 message_type
.您需要基类 Message
的唯一原因是,如果您想更广泛地讨论消息,请使用后期绑定(bind)。虽然拥有基类也会静态地强制签名在声明中匹配,而不是给出奇怪的错误......有时......在代码的遥远部分因为你在其中一个类中错误声明了一个方法(但不是其他)。
可以肯定的是,您还希望 BigMessage::bits_
为 [(size-1)/ChunkSize + 1]
,这只是上限而不是地上。这样您实际上就有足够的 Bits
es 来容纳您所有的位。
关于C++类成员隐藏规则: Design question,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5944270/