Компиляция ошибок в классе с пользовательскими функциями - PullRequest
0 голосов
/ 09 ноября 2019

Я пытаюсь создать класс, который хранит пользовательскую функцию внутри него для дальнейшего использования. Я решил использовать для этого объект boost::function.

Однако при компиляции я получаю следующую ошибку:

error: no match for ‘operator=’ in ‘((SomeClass*)this)->SomeClass::someFunction = ((SomeClass*)this)->SomeClass::DefaultFunction’

Я не понимаю этогоошибка, поскольку someFunction и DefaultFunction, насколько я вижу, должны иметь одинаковые типы.

Код показан ниже:

#include <boost/function.hpp>

class SomeClass{
    private:
            boost::function<int(int)> someFunction;
            int DefaultFunction(int i);

    public:
            SomeClass();
            ~SomeClass();
            void SetFunction(int (*f)(int));
    };

int SomeClass::DefaultFunction(int i){
    return i+1;

}

SomeClass::SomeClass(){
    someFunction=DefaultFunction;
}

~SomeClass::SomeClass(){

 }

 void SomeClass::SetFunction(int (*f)(int i)){
        someFunction=f;
 }

 void MyProgram(){
        SomeClass s;
 }

Может кто-нибудь предложить какие-либо указатели относительно того, какпостроить такой объект? В качестве альтернативы, если есть лучший способ, чем тот, который я пробую, не могли бы вы мне это объяснить?

С наилучшими пожеланиями!

Ответы [ 2 ]

1 голос
/ 09 ноября 2019

DefaultFunction является функцией-членом SomeClass. Функция-член вызывается для некоторого экземпляра SomeClass. Эта функция принимает «скрытый» указатель на экземпляр SomeClass в качестве первого добавления параметра к int. Таким образом, функция-член - это не то же самое, что свободная функция.

Ваш someFunction является объектом boost::function, поэтому он является оберткой для вызываемого объекта. Ваши требования к этому объекту: take int и возвращает int. Чтобы присвоить DefaultFunction (как функцию-член) для someFunction, вам нужно создать этот вызываемый объект. Здесь вам нужно указать, для какого экземпляра SomeClass этот объект будет вызываться, для этого используйте boost::bind:

SomeClass::SomeClass(){
    someFunction=boost::bind(&SomeClass::DefaultFunction, this, boost::placeholders::_1);
}

В приведенном выше коде вы создаете вызываемый объект, который будет вести себя как

struct unnamedClass {
    SomeClass* sc;
    unnamedClass (SomeClass* sc) : sc(sc) {} // here sc is this of SomeClass

    int operator()(int arg)
    {
        return sc->DefaultFunction(arg);
    }
};

, поэтому, когда вы вызываете someFunction(10), он принимает 10 в качестве аргумента и вызывает DefaultFunction для текущего this экземпляра.

Это

void SomeClass::SetFunction(int (*f)(int i)){
    someFunction=f;
 }

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

0 голосов
/ 09 ноября 2019

Используя ответ @ rafix07, был скомпилирован следующий код:

#include <iostream>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/bind/placeholders.hpp>

class SomeClass{
private:

public:
        SomeClass();
        ~SomeClass();
        boost::function<int(int)> someFunction;
        int DefaultFunction(int i);
        void SetFunction(int (*f)(int));
};

int SomeClass::DefaultFunction(int i){
     return i+1;
 }

SomeClass::SomeClass(){ 
someFunction=boost::bind(&SomeClass::DefaultFunction, this, _1);

}

SomeClass::~SomeClass(){
}

void SomeClass::SetFunction(int (*f)(int i)){
   someFunction=f;
}

int MyOwnProgram(int i){
    return i+2;
}

void MyProgram(){
    SomeClass s;
    std::cout<<s.someFunction(2)<<std::endl;
    s.SetFunction(MyOwnProgram);
    std::cout<<s.someFunction(2)<<std::endl;
}

int main()
{
    MyProgram();
}

Вывод из программы:

3
4
...