Статическая функция, необходимая для работы с членами класса C ++ - PullRequest
6 голосов
/ 24 февраля 2012

Я должен сделать какой-то мост между двумя частями программного обеспечения, но столкнулся с проблемой, с которой я не знаю, как справиться.Надеюсь, у кого-то будут интересные и (желательно) рабочие предложения.

Вот предыстория: у меня есть программный пакет C ++.Я должен заменить некоторую функцию в данном классе другой функцией, что нормально.Проблема в том, что новая функция вызывает другую функцию, которая должна быть статической, но должна иметь дело с членами класса.Это вторая функция, которая сводит меня с ума.

Если функция не является статической, я получаю следующую ошибку:

error: argument of type ‘void (MyClass::)(…)’ does not match ‘void (*)(…)’

Если я установил ее на статическую, я получаю либо следующую ошибку:

error: cannot call member function ‘void
MyClass::MyFunction(const double *)’ without object

или

error: ‘this’ is unavailable for static member functions

в зависимости от того, использую ли я ключевое слово "this" ("Function ()" или "this-> Function ()").

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

Как бы вы справились с таким делом с минимальным переписыванием?

Редактировать: Хорошо, вот упрощенный пример того, что я должен сделать, надеясь, что это ясно и правильно:

// This function is called by another class on an instance of MyClass
MyClass::BigFunction()
{

    …
// Call of a function from an external piece of code, 
// which prototype I cannot change
    XFunction(fcn, some more args);
    …

}


// This function has to be static and I cannot change its prototype,
// for it to be passed to XFunction.  XFunction makes iterations on it
// changing parameters (likelihood maximization) which do not appear 
// on this sample
void MyClass::fcn(some args, typeN& result) 
{

// doesn't work because fcn is static
    result = SomeComputation();

// doesn't work, for the same reason
    result = this->SomeComputation(); 

// doesn't work either, because MyClass has many parameters
// which have to be set
    MyClass *tmp = new MyClass();
    result = tmp->SomeComputation();

}

Ответы [ 4 ]

3 голосов
/ 24 февраля 2012

Указатели на нестатические функции-члены немного сложны.Самый простой обходной путь - просто добавить непрозрачный аргумент-указатель в вашу функцию, который затем можно привести как указатель на «this», а затем сделать с ним то, что вам нужно.

Вот очень простой пример:

void doSomething(int (*callback)(void *usrPtr), void *usrPtr)
{
    // Do stuff...
    int value = callback(usrPtr);
    cout << value << "\n";
}

class MyClass
{
public:
    void things()
    {
        value_ = 42;
        doSomething(myCallback, this);
    }

private:
    int value_;

    static int myCallback(void *usrPtr)
    {
        MyClass *parent = static_cast<MyClass *>(usrPtr);
        return parent->value_;
    }
};

int main()
{
    MyClass object;
    object.things();
    return 0;
}

В этом примере myCallback() может получить доступ к приватному value_ через непрозрачный указатель.

Если вам нужен более C ++-подобный подход, вы можете использовать Boost.Function и Boost..Bind, который позволяет вам передавать нестатические функции-члены как обратные вызовы:

void doSomething(boost::function<int ()> callback)
{
    // Do stuff...
    int value = callback();
    cout << value << "\n";
}

class MyClass
{
public:
    void things()
    {
        value_ = 42;
        doSomething(boost::bind(&MyClass::myCallback, this));
    }

private:
    int value_;

    int myCallback()
    {
        return value_;
    }
};

int main()
{
    MyClass object;
    object.things();
    return 0;
}

Если вы действительно не можете изменить прототип функции, вы можете использовать глобальный указатель, но это открывает все виды проблем, еслиу вас когда-нибудь будет более одного экземпляра вашего класса.Это просто плохая практика.

class MyClass;
static MyClass *myClass;

void doSomething(int (*callback)())
{
    // Do stuff...
    int value = callback();
    cout << value << "\n";
}

class MyClass
{
public:
    void things()
    {
        value_ = 42;
        myClass = this;
        doSomething(myCallback);
    }

private:
    int value_;

    static int myCallback()
    {
        return myClass->value_;
    }
};

int main()
{
    MyClass object;
    object.things();
    return 0;
}
2 голосов
/ 25 февраля 2012

Следуя предложению spencercw ниже первоначального вопроса, я попробовал решение «статическая переменная-член, которое вы указали для this» (глобальная переменная была бы хитрой и опасной в контексте набора программ).

На самом деле я понял, что в коде уже реализовано что-то подобное: (1001 *

) я не использовал:* Это работает, спасибо !!!

0 голосов
/ 24 февраля 2012

Вы можете переместить result = SomeComputation(); из вашей статической функции и поместить ее в BigFunction прямо перед вызовом статической функции.

0 голосов
/ 24 февраля 2012

не реентерабельный и не потокобезопасный способ - передать этот адрес с помощью глобальной переменной.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...