Указатель на тип члена несовместим с типом объекта → В чем причина? - PullRequest
0 голосов
/ 04 ноября 2018

Недавно я столкнулся с ошибкой компилятора (GNU g ++ 4.9.2), подобной этой:

ProceduralTimerTaskAdapter.cpp:25:13: error: pointer to member type ‘void (Poco::Util::Timer::)(Poco::Util::TimerTask&)’ incompatible with object type ‘Poco::Util::ProceduralTimerTaskAdapter’

Вот соответствующий код (который почти самодостаточен, за исключением необходимых библиотек Poco):

ProceduralTimerTaskAdapter.h:

#include <Poco/Util/Timer.h>
#include <Poco/Util/TimerTask.h>
#include <Poco/Util/TimerTaskAdapter.h>

#ifndef PROCEDURALTIMERTASKADAPTER_H
#define PROCEDURALTIMERTASKADAPTER_H

using namespace std;
using namespace Poco::Util;

typedef void (*Callback) (TimerTask&);

namespace Poco {
  namespace Util {
    class ProceduralTimerTaskAdapter : public TimerTaskAdapter <Timer> {
    public:
      ProceduralTimerTaskAdapter (Callback procedure); // Constructor

      void run (); // Method defining the main thread
    protected:
      ~ProceduralTimerTaskAdapter (); // Destructor (not for general use)
    private:
      ProceduralTimerTaskAdapter (); // Default constructor (not for general use)

      Callback procedure; // The callback procedure called by the timer.
    };
  }
}

#endif

ProceduralTimerTaskAdapter.cpp:

// This is the implementation of the ProceduralTimerTaskAdapter class.

#include <iostream>
#include <Poco/Util/Timer.h>
#include <Poco/Util/TimerTask.h>
#include <Poco/Util/TimerTaskAdapter.h>
#include "ProceduralTimerTaskAdapter.h"

using namespace std;
using namespace Poco::Util;

ProceduralTimerTaskAdapter::ProceduralTimerTaskAdapter (Callback procedure) : TimerTaskAdapter<Timer>::TimerTaskAdapter (*(new Timer ()), procedure)
{
  this -> procedure = procedure;
}

ProceduralTimerTaskAdapter::~ProceduralTimerTaskAdapter ()
{
}

void ProceduralTimerTaskAdapter::run ()
{
  TimerTask &task = *this;

  (this ->* procedure) (task);
}

На самом деле я хочу построить расширение хорошо известного TimerTaskAdapter для обработки функций обратного вызова, которые не связаны с определенным классом (потому что они расположены в main.cpp, например). Я переопределяю виртуальный метод run () очень простым самодельным, который вызывает обратный вызов. После того, как я обработал несколько разных ошибок, я столкнулся с очевидным несоответствием классов, которое не могу решить сам. Я даже не понимаю, почему компилятор указывает имя класса, имя которого Poco::Util::Timer:: (Почему оно заканчивается ::?). Поскольку ProceduralTimerTaskAdapter определяет член с именем procedure, почему компилятор ожидает другой класс?

Спасибо.

Ответы [ 2 ]

0 голосов
/ 04 ноября 2018

Синтаксис ->* предполагает наличие левого оператора указателя типа на объект класса (например, this) и правого оператора указателя типа на функцию-член этого класса. Но в

TimerTask &task = *this;          // line 24
(this ->* procedure) (task);      // line 25

procedure не является указателем на функцию-член ProceduralTimerTaskAdapter. Так что твой код плохо сформирован. procedure - это просто указатель на свободную (не являющуюся членом) функцию, принимающую TimerTask& и возвращающую void. Если ProceduralTimerTaskAdapter получено из TimerTask тогда следующий код должен скомпилироваться

TimerTask &task = *this;
(this -> procedure) (task);

или короче

procedure(*this);

, используя тот факт, что указатели на функции могут синтаксически использоваться как функция.


Edit. Похоже (из ваших комментариев к другому ответу), что ваш код был неправильно сформирован еще одним способом, а именно, что ProceduralTimerTaskAdapter не было получено из TimerTask. Тогда, конечно, строка 24 (а не только 25) должна выдавать ошибку. Поэтому кажется, что вы не показали нам точно такой же код, как тот, который создал сообщение об ошибке, или не все ошибки, которые оно вызывает.

0 голосов
/ 04 ноября 2018

Получите из Poco::Util::TimerTask (как в Poco::Util::TimerTaskAdapter классе) и переопределите run метод, в котором вы будете вызывать процедуры.

class ProcedureAdapter : public Poco::Util::TimerTask {
public:

    typedef void (*Callback)(TimerTask&);

    ProcedureAdapter (Callback c) : callback(c) {;}

    void run () {
        callback(*this); // call some procedure which takes TimerTask
    }

    Callback callback;
};

void fun (Poco::Util::TimerTask&) {
    cout << "fun was invoked" << endl;
}

void fun2 (Poco::Util::TimerTask&) {
    cout << "fun2 was invoked" << endl; 
}

int main()
{
    Poco::Util::Timer t;
    t.schedule (new ProcedureAdapter{&fun},1,1);
    t.schedule (new ProcedureAdapter{&fun2},1,1);
...