C++类成员隐藏规则:设计问题
我有一个基类 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>位_[0];
和 SmallMessage< 16 >
将包含 Bits< 16>据我了解,bits_
将隐藏原始的零大小的成员。
我知道有几种方法可以处理这个问题:
- 声明一个
bits_
之外的名称,并提供一个重写的接口 - 修改
SmallMessage
以隐藏Message 的所有方法
处理bits_
和本地实现 - 将
Message
中的方法设为虚拟
我的问题是这两种方法是否有好处,或者是否有更好的方法为各种大小的内存容器提供接口上面解释过。
最终,我希望有一些类似的东西:
typedef MakeMessage< FooMessage, 16 >::type message_type;
// ...
message_type message;
message.doSomethingToBits ();
无论实际使用什么容器,都以相同的方式工作。
I've got a base class, Message
, that dictates policy. I've also got derivations of that class for specific message instances.
Consider this simplified example:
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;
};
If ChunkSize
is 32 and I generate the following:
MakeMessage< FooMessage, 16 >
The Message< 16 >
will result in a Bits< 32 > bits_[0];
and SmallMessage< 16 >
will contain Bits< 16 > bits_
which, as I understand it, will shadow the original, zero-sized member.
There are a couple of ways I know to handle this:
- Declare a name other than
bits_
and provide an overridden interface to that - Modify
SmallMessage
to hide all methods ofMessage
that deal withbits_
with local implementations - Make the methods in
Message
virtual
My question is whether there is a benefit to either approach or if there is a better way to provide an interface to various sized memory containers as explained above.
Ultimately, I'd like to have something along the lines of:
typedef MakeMessage< FooMessage, 16 >::type message_type;
// ...
message_type message;
message.doSomethingToBits ();
Work the same regardless of what container is actually being used.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
好吧,尽我所能地通过大量的
template
和typename
,您试图使用继承进行组合,这被认为是错误的方法。SmallMessage
这里不是一种Message
,因为正如您所注意到的,它不支持处理bits_
以同样的方式排列。我认为正确的方法是将
Message
作为抽象基类(重要:没有任何类型的bits_
,可能很多纯虚函数),然后是SmallMessage
和BigMessage
作为实现。另外,由于您无论如何都使用模板,因此类型是在编译时确定的,并且实际上可能根本没有理由使用Message
。只要SmallMessage
和BigMessage
具有相同的签名,您就可以按照您的描述使用message_type
,即使它们没有共同的基类。您需要基类Message
的唯一原因是您想使用后期绑定更广泛地讨论消息。尽管拥有基类也会静态地强制声明中的签名正确匹配,而不是给出奇怪的错误...有时...在代码的较远部分,因为您错误地声明了其中一个类中的方法(但不是其他)。可以肯定的是,您还希望
BigMessage::bits_
为[(size-1) / ChunkSize + 1]
,这只是上限而不是下限。这样,您实际上就有了足够的位来容纳您的所有位。Well, as best as I can forge through this mass of
template
andtypename
, you're trying to use inheritance for composition, which is considered the wrong way to do it.SmallMessage
here is not a type ofMessage
, because as you note it doesn't support dealing with thebits_
array in the same manner.I think the right way to do this would be to have
Message
as an abstract base class (important: nobits_
of any kind, probably lots of pure virtual functions), and thenSmallMessage
andBigMessage
as implementations. Also, since you're using templates for everything anyway, the types are worked out at compile time, and there might not actually be a reason to haveMessage
at all. As long asSmallMessage
andBigMessage
have the same signature, you can usemessage_type
as you describe even if they don't have a common base class. The only reason you would need the base classMessage
is if you want to talk about messages more generally, using late binding. Although having the base class will also statically enforce that the signatures match right in the declaration, rather than giving strange errors... sometimes... in distant parts of the code because you misdeclared a method in one of the classes (but not the other).It's a safe bet you also want the
BigMessage::bits_
to be[(size-1) / ChunkSize + 1]
, which is just the ceiling rather than the floor. This way you actually have enoughBits
es to fit all your bits.