Эквивалентность функций и указателей на функции

У меня есть два класса; класс A уведомляет класс B о некоторых событиях.

typedef void (*callbackb) (B *, int param1);

class A
{
  callbackb callme;
  B *parent;
};

class B
{
  A ai;
  void set_cb() { ai.callme = cb_handler; }
  static void cb_handler (B *obj, int param1) { obj->real_handler(param1); }
  void real_handler(int param1);
};

Есть два эквивалентных объявления, callbackb и cb_handler, но одно из них является указателем на функцию, а другое - функцией. Можно ли изменить один или оба, чтобы оба были связаны с одним объявлением прототипа?

1 ответ

Решение

Вы не можете определить cb_handler Как ты хочешь. Но вы, безусловно, можете объявить их на основе одного и того же прототипа, и компилятор проверит это. Это также мешает вам скрыть семантику указателя, и это хорошо. Вот как:

  1. Определите обратный вызов как тип функции:

    typedef void callbackb(B *, int param1);
    
  2. Объявите указатель и статический член в терминах типа CB:

    class A
    {
      callbackb *callme; // The pointer is explicit
      B *parent;
    };
    
    // Later
    class B
    {
      // ...
      static inline callbackb cb_handler; // This is a function declaration
    };
    // And this is the inline definition, you can put it in a header
    inline void B::cb_handler (B *obj, int param1) { obj->real_handler(param1); }
    

А сейчас cb_handler а также callme объявлены в терминах того же типа. Вы должны указать полный прототип при определении cb_handler, но это все еще может быть inline внеклассное определение в заголовке.

Компилятор проверит, что определение cb_handler соответствует декларации, поэтому вы будете уведомлены, если cb_handler отличается от callbackb,

Другие вопросы по тегам