константная ссылка на указатель на функцию - PullRequest
1 голос
/ 30 июня 2011

У меня есть функция Foo и класс CDelegate.

typedef void (*typeFctPtr)(void*);


void Foo(void* dummy)
{
  cout << "Foo\n";
}


class CDelegate 
{ 
  public:

  CDelegate (const typeFctPtr& f_ref_Wrapper, void* f_pvSubscriber) 
    : m_ref_Wrapper(f_ref_Wrapper), m_pvSubscriber(f_pvSubscriber) 
  {
  }

  inline void operator () () const
  {
    (*m_ref_Wrapper)(0);
  }

  inline void operator=(const CInterruptDelegate& D)
  {
  }

private:
  void* m_pvSubscriber;
  const typeFctPtr& m_ref_Wrapper;
};

Второй класс имеет статический член static CDelegate m_Delegate;, который я инициализирую с помощью конструктора следующим образом:

CInterruptDelegate CSpi1::m_Delegate(FreeFunction, 0);

Я хочу вызвать Foo, вызвав оператор () моего статического объекта: CSpi1::m_Delegate();

Я получаю исключение на (*m_ref_Wrapper)(0); Что-то не так с синтаксисом? Я не совсем уверен, возможно ли вообще то, что я пытаюсь сделать. У меня есть рабочее решение, где конструктор CDelegate не принимает константную ссылку на указатель функции, а сам указатель на функцию. Затем я могу без проблем вызвать функцию в операторе (). Я хочу использовать ссылку const, потому что вызов указателя функции не может быть оптимизирован, и я надеюсь, что вызов через ссылку const может, потому что все должно быть известно во время компиляции.

Ответы [ 2 ]

1 голос
/ 30 июня 2011

Я считаю, что проблема заключается в объявлении члена:

const typeFctPtr& m_ref_Wrapper;

Вместо этого попробуйте сбросить &:

const typeFctPtr m_ref_Wrapper;

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

Пока мы работаем над этим, я бы посоветовал вам удалить ссылку изконструктор также.Причина этого заключается в том, что при работе со скаляром нет никакой выгоды: s.

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

Ниже приведена сокращенная версия, в которой кратко изложены изменения, которые я предлагаю выше:

typedef void (typeFct)(void*);

class CDelegate
{
  public:

  CDelegate (typeFct * f_Wrapper, void* f_pvSubscriber)
    : m_ref_Wrapper(f_Wrapper), m_pvSubscriber(f_pvSubscriber) 
  {
  }

  inline void operator () () const
  {
    (*m_ref_Wrapper)(0);
  }

private:
  void* m_pvSubscriber;
  typeFct * m_ref_Wrapper;
};
1 голос
/ 30 июня 2011

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

Попробуйте изменить typedef на тип функции:

typedef void typeFct(void*);
...
const typeFct & m_ref_Wrapper;

Тогда с вашим существующим кодом вы получите ссылку на функцию, и все будет в порядке. Или вы можете сохранить указатель на функцию - const typeFct *.

И в любом случае вызов может быть просто m_ref_Wrapper(0).

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

...