C++类成员隐藏规则:设计问题

发布于 2024-11-06 05:55:30 字数 1529 浏览 0 评论 0原文

我有一个基类 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 >

Message16 > 将导致 Bits<; 32>位_[0];SmallMessage< 16 > 将包含 Bits< 16>据我了解,bits_ 将隐藏原始的零大小的成员。

我知道有几种方法可以处理这个问题:

  1. 声明一个 bits_ 之外的名称,并提供一个重写的接口
  2. 修改 SmallMessage 以隐藏 Message 的所有方法 处理 bits_ 和本地实现
  3. 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:

  1. Declare a name other than bits_ and provide an overridden interface to that
  2. Modify SmallMessage to hide all methods of Message that deal with bits_ with local implementations
  3. 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

停滞 2024-11-13 05:55:30

好吧,尽我所能地通过大量的 templatetypename,您试图使用继承进行组合,这被认为是错误的方法。 SmallMessage 这里不是一种Message,因为正如您所注意到的,它不支持处理bits_以同样的方式排列。

我认为正确的方法是将 Message 作为抽象基类(重要:没有任何类型的 bits_,可能很多纯虚函数),然后是 SmallMessageBigMessage 作为实现。另外,由于您无论如何都使用模板,因此类型是在编译时确定的,并且实际上可能根本没有理由使用 Message 。只要 SmallMessageBigMessage 具有相同的签名,您就可以按照您的描述使用 message_type,即使它们没有共同的基类。您需要基类 Message 的唯一原因是您想使用后期绑定更广泛地讨论消息。尽管拥有基类也会静态地强制声明中的签名正确匹配,而不是给出奇怪的错误...有时...在代码的较远部分,因为您错误地声明了其中一个类中的方法(但不是其他)。

可以肯定的是,您还希望 BigMessage::bits_[(size-1) / ChunkSize + 1],这只是上限而不是下限。这样,您实际上就有了足够的位来容纳您的所有位。

Well, as best as I can forge through this mass of template and typename, you're trying to use inheritance for composition, which is considered the wrong way to do it. SmallMessage here is not a type of Message, because as you note it doesn't support dealing with the bits_ array in the same manner.

I think the right way to do this would be to have Message as an abstract base class (important: no bits_ of any kind, probably lots of pure virtual functions), and then SmallMessage and BigMessage 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 have Message at all. As long as SmallMessage and BigMessage have the same signature, you can use message_type as you describe even if they don't have a common base class. The only reason you would need the base class Message 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 enough Bitses to fit all your bits.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文