Какая польза от класса C ++, содержащего указатель на «реализацию» и «интерфейс»? - PullRequest
0 голосов
/ 03 марта 2010

Я изучаю некоторые исходные коды и мне просто интересно, почему класс (или классы) часто реализуется таким образом:


class EventHandler
{
...
    EventDispatcher* m_Dispatcher;
    virtual bool ProcEvent( EventHandler* Sender, int Task, int Event, void* Param );
...
};

class ClassA: public EventHandler
{
...
    ClassA* m_Impl;
    ClassA* m_Iface;
...
public:
    // virtual functions
    virtual bool ProcEvent( EventHandler* Sender, int Task, int Event, void* Param );
    virtual void OnDataWritten(const PIOResult&) {;}
    ...

    // sample functions
    void SetImplement( ClassA* aImpl );
    void SetInterface( ClassA* aIface );
    ClassA* GetImplement() { return m_Impl; }
    ClassA* GetInterface() { return m_Iface; }
    bool GetData( list& aList );
};

// Implementation of some sample functions; Most of its function contain more
// or less the same format as below, with the return m_Impl->XXX having the same
// name as the function being defined (e.g. A::XXX)
bool ClassA::GetData( list&lt Data &gt& aList )
{
    if( m_Impl )
        return m_Impl->GetData( aList );
    else
        return false;
}

class ClassAFactory: public EventHandler
{
private:
    ClassAFactory* m_Impl;
    ClassAFactory* m_Iface;

protected:
    virtual ClassA* MakeTransport();

    virtual bool ProcEvent( EventHandler* Sender, int Task, int Event, void* Param );
    virtual ClassA* CreateClassA() { return 0; }

...
};

// In some member function of ClassB (ClassB inherits ClassA)

switch( status )
{
    case 1:
        GetInterface()->OnDataWritten();
    case 2:
        // ...
};


Я верю, что это некий шаблон дизайна, но я не знаком с ним. Это может помочь мне понять, если я знаю, что это такое. Может кто-нибудь помочь мне указать, что это может быть или для чего используются эти классы, так что он реализован таким образом?

Я думаю, что это для обработки событий и используется вместе с какой-то фабрикой, но я не уверен.

Ответы [ 4 ]

2 голосов
/ 03 марта 2010

Боюсь, что используемые имена не имеют значения usual, поэтому без примеров того, что вставлено или как они используются, будет трудно догадаться.

Необходимо проверить 2 шаблона проектирования, которые интенсивно используют этот вид self-recursion (на уровне класса *):

И я боюсь, что вы смотрите на то, что не подражает ни одному из них.

В Decorator смысл заключается в добавлении функциональности. Для этого у вас есть Interface, из которого происходит класс Concrete и интерфейс Wrapper. Тогда различные обёртки получатся из Wrapper, и вы можете их связать:

Interface* interface = new Wrapper2( new Wrapper1 ( new Concrete() ) );

Каждая оболочка добавляет некоторую функциональность, тогда как здесь у нас только идеальная пересылка ... так что это не Decorator.

Шаблон Composite отличается. Его цель - скрыть, обрабатываете ли вы набор элементов или один элемент. Обычный пример - дерево: вы можете применять операции либо ко всему поддереву, либо к листовому узлу, если он реализован с использованием шаблона Composite.

Еще раз, здесь нет такого понятия.

Так что я предпочитаю, что у вас либо дикий дизайн (возможно, ошибочная попытка подражать известному шаблону), либо вы не дали достаточно информации (исходного кода), чтобы мы могли выяснить роль. В любом случае это кажется странным.

* Примечание: под self-recursion на уровне класса я имею в виду, что объект класса A указывает на другой объект класса A, но это не означает (безусловно), что он указывает на тот же экземпляр .. иначе у нас было бы переполнение стека (каламбур). Этот не тот же экземпляр бит, безусловно, стоит проверить во время вызова SetImplementation: обратите внимание, что любая циклическая ссылка может привести к смерти в результате рекурсии.

2 голосов
/ 03 марта 2010

Я дико догадываюсь, но может ли это быть "идиома pimpl", которую вы ищете? http://www.gamedev.net/reference/articles/article1794.asp

EDIT
Пример расширенного кода с реализацией GetData, безусловно, является примером идиомы pimpl. Однако это не объясняет член m_Iface. Можете ли вы привести пример, где это тоже используется?

EDIT2
С добавленным примером того, как отображается m_Iface, становится ясно, что я был неправ в отношении pimpl. Это своего рода декоратор. M_Impl указывает на базовый объект, а m_Iface указывает на самый внешний уровень, так что базовый объект может выполнить вызов, который проходит через всю цепочку декораторов. Этот пример немного сложен, поскольку ClassA является классом интерфейса и реализацией по умолчанию. Если вы хотите создать декоратор для класса, вам придется наследовать ClassA.

0 голосов
/ 03 марта 2010

Я не уверен, является ли это классическим примером идиомы pimpl, но если это так, смысл состоит в том, чтобы отделить интерфейс (который должен быть стабильным) от деталей реализации (что вы должны быть относительно свободны для меняется).

0 голосов
/ 03 марта 2010

Это выглядит гораздо больше C, чем C ++. В любом объектно-ориентированном языке вы должны использовать наследование и виртуальные функции, чтобы получить такое поведение.

Использование внутреннего указателя на класс реализации прекрасно (идиома pimpl), но этот указатель обычно не будет доступен для вызывающих. И я вообще не получаю указатель на интерфейс.

...