Мне нужно создать простой обратный вызов в C ++? Должен ли я использовать boost :: function? - PullRequest
2 голосов
/ 04 марта 2009

Предположим, у меня есть такой код:

class Visitor {
   public:
      Visitor(callBackFunction) {}
      void visit() {
          //do something useful
          invokeCallback();
      }
}

class ClassThatCanBeVisited {
    Visitor &visitor;

    public:
       ClassThatCanBeVisited(Visitor &_visitor) : visitor(_visitor){}
       void someUsefulMethod() {
          int data= 42;
          visitor.visit(data);
       }
};


void callBackFunction() {
    //do something useful in the context of the Main file
}
int main() {
     Visitor visitor;
     ClassThatCanBeVisited foo(visitor);
     foo.someUsefulMethod();
}

Мне нужно создать простой обратный вызов, который будет вызываться всякий раз, когда вызывается Visitor :: visit (). Я знаю, что, вероятно, мне следует поместить код обратного вызова в мой Visitor, но он находится в другом контексте, поэтому я хотел бы передать callBackFunction () посетителю, чтобы он мог вызвать мою функцию обратного вызова.

Я искал что-то в Интернете и увидел boost :: function, но в c ++ уже есть основные функторы.

Какой из них использовать для большей ясности кода? Обратный вызов будет простой функцией void (), но он может расти, вы никогда не узнаете будущее:)

Каков рекомендуемый способ сделать это?

Ответы [ 3 ]

7 голосов
/ 04 марта 2009

Да, Boost :: function сделает это хорошо. Это очень распространенное использование. Вам нужно будет использовать boost :: bind для привязки экземпляра к функции-члену.

 func = boost::bind( &MyClass::CallbackFunc, this);

Было бы так, как бы вы делали это из класса.

Убедитесь, что "this" не исчезнет, ​​иначе ваша функция повышения будет зависать где-то в середине какого-то заголовка повышения.

4 голосов
/ 04 марта 2009

Вы можете использовать интерфейс обратного вызова и его иерархию, если не хотите использовать boost :: function.

class VisitorCallback
{
public:
    virtual void handle( const Visitor& ) = 0;
};

Если вы используете или можете использовать boost :: function - используйте его, это хороший способ избавиться от всех этих классов обратного вызова.

Edit:
@edisongustavo:

boost :: function и boost :: bind, вероятно, не сделает ваш код более читабельным. Но это даст вам возможность передавать свободные функции (я имею в виду функции из класса и функции статического класса) в качестве обратного вызова, а также существующие функции любого класса.

С помощью функций повышения вы можете передавать функции с, например, 2 параметрами в качестве обратного вызова, которые ожидают только один параметр.

typedef boost::function< void ( int ) > IntExpectingCallback;

void TwoIntFunction( int, int );
{
}
...
IntExpectingCallback callback = boost::bind( TwoIntFunction, 5, _1 );

Но, опять же, это не сделает ваш код более читабельным, если ваша команда не знает и не поддерживает повышение.

1 голос
/ 23 апреля 2009

Приведенные выше ответы великолепны, но я просто хотел бы указать на то, что вы упомянули в своем вопросе, и которое все еще имеет отношение к вашему выбору между объектами обратного вызова C ++ (в ответе Николая) и boost.

"обратный вызов будет простой функцией void (), но он может расти, вы никогда не узнаете будущее :)"

Это, вероятно, наихудшая причина лишних, ненужных функций - то есть «на тот случай, если вам это нужно». Если вы не знаете - тогда не делайте больше, чем необходимо, скорее всего, ваше предположение будет неверным, особенно к тому времени, когда оно вам понадобится.

С другой стороны, если вы знаете, что весьма вероятно, что вам понадобится функциональность очень скоро , то, возможно, стоит добавить ее.

Еще раз, чтобы повторить то, что сказал Николай - если у вас уже есть повышение в вашем проекте, и вашей команде это нравится, то используйте это, но в противном случае это может быть излишним.

...