Обратные вызовы в C++ | страница 17



>  virtual void callbackHandler2(int eventID);

>};


>class Executor1: public Executor

>{

>public:

>  void callbackHandler1(int eventID) override;

>};


>class Executor2: public Executor

>{

>public:

>  void callbackHandler2(int eventID) override;

>};


>class Executor3: public Executor1, public Executor2

>{

>};


Рис. 13. Иерархия наследования классов-исполнителей


Итак, будем назначать различные указатели на экземпляры классов и методы-члены, как показано в Листинг 13.

Листинг 13. Настройка указателей на классы и методы

>int main()

>{

>  Initiator initiator;

>  Executor  executor;

>  Executor1 executor1;

>  Executor2 executor2;

>  Executor3 executor3;


>  initiator.setup(&executor, &Executor::callbackHandler1);   // (1)

>  initiator.setup(&executor, &Executor::callbackHandler2);   // (2)

>  initiator.setup(&executor1, &Executor::callbackHandler1);  // (3)

>  initiator.setup(&executor1, &Executor::callbackHandler2);  // (4)

>  initiator.setup(&executor2, &Executor::callbackHandler1);  // (5)

>  initiator.setup(&executor2, &Executor::callbackHandler2);  // (6)


>  //initiator.setup(&executor3, &Executor::callbackHandler1); //Incorrect, base class is ambiguous  // (7)

>  //initiator.setup(&executor3, &Executor::callbackHandler2); //Incorrect, base class is ambiguous  // (8)


>  initiator.setup((Executor1*)&executor3, &Executor::callbackHandler1);  // (9)

>  initiator.setup((Executor1*)&executor3, &Executor::callbackHandler2);  // (10)

>  initiator.setup((Executor2*)&executor3, &Executor::callbackHandler1);  // (11)

>  initiator.setup((Executor2*)&executor3, &Executor::callbackHandler2);  // (12)

>}


В строках 1 и 2 все прозрачно: какой метод назначен, такой и будет вызван.

В строке 3 мы назначаем указатель на метод Executor::callbackHandler1, но поскольку в классе Executor1 он переопределен, будет вызван метод Executor1::callbackHandler1.

В строке 4 мы назначаем указатель на Executor::callbackHandler2; в классе Executor1 такого метода нет (т.е. он не переопределен), поэтому будет вызван метод базового класса Executor::callbackHandler2.

В строке 5 мы назначаем указатель на Executor::callbackHandler1; в классе Executor2 метод не переопределен, поэтому будет вызван метод базового класса Executor::callbackHandler2.

В строке 6 мы назначаем указатель на Executor::callbackHandler2; в классе Executor2 он переопределен, поэтому будет вызван метод Executor2:: callbackHandler2.

С классом Executor3 ситуация еще интереснее, поскольку он использует множественное наследование