2016-12-16 8 views
0

Я хочу передать мой класс Worker указатель на Funtion, но что-то не так, когда им нужно вызвать конструктор ...Как передать функцию-член в конструктор класса?

Worker.h

class Worker : public QObject 
{ 
Q_OBJECT 

public: 
Worker(void (*process)()); 

public slots: 
void work(); 

signals: 
void error(QString error); 
void paused(); 

private: 
void (*_task)(); 
}; 

Worker.cpp:

Worker::Worker(void (*task)()) 
{ 
_task = task; 
} 

void Worker::work() 
{ 
_task(); 
paused(); 
} 

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

main.cpp:

_worker = new Worker(someClass->Update()); 
+0

Возможно, вам захочется узнать о ['std :: function'] (http://en.cppreference.com/w/cpp/utility/functional/function) и [' std :: bind'] (http: //en.cppreference.com/w/cpp/utility/functional/bind). –

+0

Что касается вашей проблемы, вы * вызываете * функцию 'Update'. Вы не передаете функцию конструктору, а его результат. –

ответ

3

Во-первых, когда функция является функцией non static членом класса, его первый аргумент является объект, из которого его вызвали.

В вашем примере, реальный код для функции Update() от объекта someClass является «недействительным Update (& SomeClass)»

Во-вторых, когда вы Update(), вы вызываете функцию и так, берет свое возвращение в ваш конструктор Worker.

Для использования указателей на функции-члены, синтаксис: &ClassType::FunctionName

Чтобы использовать «нормальные» указатели на функции, синтаксис: &FunctionName

В вашем Exemple, вы можете для Exemple функции поворота обновления статические и изменить конструктор так:

_worker = new Worker(&someClassType::Update); 

как кто-то сказал в комментариях, если вы хотите улучшить свой код, узнать о станде :: функция из 11

C++
0

Только вариант ответа Фелиси.

Если вы хотите иметь возможность передавать методы, работающие с произвольными объектами, путь C++ 11 будет состоять в использовании std::function и std::bind.

Если по какой-либо причине вы должны использовать предварительно системы C++ 11, вам придется вернуться к C-иш стиль прохождения произвольных аргументов, старый добрый void * типа:

void someClassUpdateWrapper(void *obj) { 
    SomeClassType someClass = static_cast<SomeClassType *>(obj); 
    someClass->Update(); 
} 

Вы будете придется немного изменить свои объявления:

class Worker : public QObject 
{ 
Q_OBJECT 

public: 
Worker(void (*process)(), void *obj); 

... 

private: 
void (*_task)(); 
void *_obj; 
}; 

затем:

Worker::Worker(void (*task)(), void *obj;) 
{ 
_task = task; 
_obj = obj; 
} 

void Worker::work() 
{ 
_task(_obj); 
paused(); 
} 

и Финлей :

_worker = new Worker(someClassUpdateWrapper, static_cast<void *>(someClass)); 

Но это теряет все возможные элементы управления типа, допускаемые C++ 11 образом - причина, почему std::function и std::bind были изобретены ...