从嵌套的

时间:2017-11-24 16:20:05

标签: c++ design-patterns

关于C ++标准和适当设计模式的问题

我有一个对象,它有几个非POD对象作为成员,从这些对象中我需要访问外部对象。

例如,它可以是“侦听”多个不同事件的对象,而侦听则意味着实现某些接口。您不能直接由主类继承此接口,因为您不能多次继承相同的基类。但即使你可以 - 你可能想要避免这种情况,因为你不想暴露这个界面,它只是你对象的实现细节。

我的意思是这样的:

class MyClass
{
    // ...
    struct Listener1 :public IEventListener {
        virtual void OnEvent() { /* need to access MyClass */ }
    } m_Evt1;

    struct Listener2 :public IEventListener {
        virtual void OnEvent() { /* need to access MyClass */ }
    } m_Evt2;
};

允许访问外部类的一种显而易见的方法是在每个内部对象中都有一个指向它的成员。但这需要编写一些代码(指针/引用的初始化),编译器不喜欢在基本成员初始化中使用this时,还有为此生成的实际代码和对象布局在内存中膨胀。

还有另一种可能性:使用offsetof - 就像诡计一样。内部对象wrt外部类的内存偏移量在编译时是已知的。因此反之亦然,即我们可以减去内部对象的偏移量,以获得指向外部类的指针。用漂亮的C ++访问器方法包装它 - 瞧。

#define IMPLEMENT_GET_PARENT_OBJ(parent_class, this_var) \
parent_class& get_ParentObj() { return * (parent_class*) (((PBYTE) this) + 1 - (PBYTE) (&((parent_class*) 1)->this_var)); }

class MyClass
{
    // ...
    struct Listener1 :public IEventListener {
        IMPLEMENT_GET_PARENT_OBJ(MyClass, m_Evt1)
        virtual void OnEvent() { get_ParentObj().OnEvent1(); }
    } m_Evt1;

    struct Listener2 :public IEventListener {
        IMPLEMENT_GET_PARENT_OBJ(MyClass, m_Evt2)
        virtual void OnEvent() { get_ParentObj().OnEvent2(); }
    } m_Evt2;

    void OnEvent1();
    void OnEvent2();
};

有人可能会争辩说,如果你在MyClass之外声明这种内部类型的对象 - 那么显然get_ParentObj()被破坏了,你得到了未定义的行为。你也可以在技术上从内部类的c'tor获取外部类的引用,甚至在它构造之前调用它的方法。

我知道有很多方法可以解决这个问题并使其变得简单,例如动态创建内部对象并为外部类提供弱引用等。 但这在我的场景中是一种矫枉过正。假设你没有故意射击自己,似乎没有问题。实际上说它只是工作,没有任何内存浪费或不需要的额外代码。

这被认为是一种好习惯吗?如果没有 - 为什么?

0 个答案:

没有答案