forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   C++ (http://forum.boolean.name/forumdisplay.php?f=22)
-   -   Укозатель на метод класса (http://forum.boolean.name/showthread.php?t=15353)

den 24.08.2011 23:56

Укозатель на метод класса
 
Имеится некая библиотечная функция, которая принимает в параметры укозатель на функцию:
PHP код:

libfunc(int (*fn)(void *)); 

она вызывается из метода класса MyClass::init, и принемать должна MyClass::someFunc.
Повсякому пробывал - компилятор ругается.
Как?
upd: если не использовать классы, то всё ок.

impersonalis 25.08.2011 00:02

Ответ: Укозатель на метод класса
 
http://forum.boolean.name/showthread.php?t=15043

den 25.08.2011 00:11

Ответ: Укозатель на метод класса
 
видел. читал. непомогает((
PHP код:

SDL_CreateThread(&net::thread, &timeout); 

Цитата:

src/net.cpp:62: error: cannot convert ‘int (net::*)(void*)’ to ‘int (*)(void*)’ for argument ‘1’ to ‘SDL_Thread* SDL_CreateThread(int (*)(void*), void*)’

impersonalis 25.08.2011 00:13

Ответ: Укозатель на метод класса
 
код, где вызваешь покажи
и без смайлов

den 25.08.2011 00:15

Ответ: Укозатель на метод класса
 
кусок файла net.cpp
PHP код:

int net::thread(void *data)
{
    
int timeout = *((int*)data);
    
ENetEvent event;
    while(
enet_host_service(client, &eventtimeout))
    {
        if(
event.type == ENET_EVENT_TYPE_RECEIVE)
        {
            
int size;
            
bytes2int(&(event.packet->data[0]), size);
            for(
int i 0sizei++)
            {
                
pair intint p;
                
bytes2int(&(event.packet->data[sizeof(int)*(i*2+1)]), p.first);
                
bytes2int(&(event.packet->data[sizeof(int)*(i*2+2)]), p.second);
                
SDL_mutexP(lock);
                
v.push_back(p);
                
SDL_mutexV(lock);
            } 
        }
        
enet_packet_destroy(event.packet);
    }
    return 
0;
}

int net::connect(string hostint portint timeout)
{
    
enet_address_set_host(&addresshost.c_str());
    
address.port port;
    
peer enet_host_connect(client, &address2);

    
ENetEvent event;
    if(
enet_host_service(client, &eventtimeout) > && event.type == ENET_EVENT_TYPE_CONNECT)
    {
        
cout << "Connection succeeded" << endl;
    }
    else
    {
        
enet_peer_reset(peer);
        
cerr << "Connection to " << host << ":" << port << " failed" << endl;
        return 
1;
    }
    
SDL_CreateThread(&net::thread, &timeout);
    return 
0;


ps: ошибок больше нет, только эта.

Mr_F_ 25.08.2011 00:17

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

den 25.08.2011 00:19

Ответ: Укозатель на метод класса
 
описание функции
все методы нестатические.

den 25.08.2011 00:25

Ответ: Укозатель на метод класса
 
сделал тупо приведение:
PHP код:

SDL_CreateThread((int(*)(void*))(&net::thread), &timeout); 

и теперь вместо ошибки предупреждение))
буде тестить

genroelgvozo 25.08.2011 11:35

Ответ: Укозатель на метод класса
 
вообще штатными средствами в си нельзя на нестатичный метод ссылку сделать
это возможно благодаря делегатам, которые есть в других языках, и которые сделал Александреску в си++ с помощью шаблонов, но таким способом, что уж лучше придумать как нибудь без делегатов
об этом написано в его книге, там он много всяких вкусностей, которых нету в си++, сделал с помощью шаблонов

HolyDel 25.08.2011 11:46

Ответ: Укозатель на метод класса
 
делай метод статичным. подумай сам - у какого именно объекта должны вызваться функция, если у тебя их будет 42?

den 25.08.2011 12:02

Ответ: Укозатель на метод класса
 
Цитата:

Сообщение от HolyDel (Сообщение 200077)
делай метод статичным. подумай сам - у какого именно объекта должны вызваться функция, если у тебя их будет 42?

а если через укозатель this ?

genroelgvozo 25.08.2011 12:14

Ответ: Укозатель на метод класса
 
так ведь этот this твоя библиотечная функция и не знает
просто ссылка на метод для всех обьектов одинакова, когда ты вызваешь метод для обьекта ему еще тайно от тебя передается указатель this
и просто так функции этот указатель не передать
и выхода два, либо как казал холидел статик, либо делегат, что в си++ изврат с садомазой))

impersonalis 25.08.2011 15:45

Ответ: Укозатель на метод класса
 
Цитата:

Сообщение от HolyDel (Сообщение 200077)
делай метод статичным. подумай сам - у какого именно объекта должны вызваться функция, если у тебя их будет 42?

Для вызова используются два указателя: на метод и на экземпляр класса. Я же уже писал: http://forum.boolean.name/showthread.php?t=15043

цель:
Код:

class MyCl{
private:
MyStr ControlThread;
void func1(WORD,void*,void*); //<---- хочу вызвать вот это
void func2(WORD,void*,void*);
void func3(WORD,void*,void*);
public:
MyCl();
~MyCl();
}

указтели:
Код:

MyCl *ParentInterface;
void (MyCl::*FunctionPtr)(WORD,void*,void*);

Получение адреса (? вообще костыльно выглядит - фактически по имеющимся данным [без указания конкретного экземпляра класса] можно восстановить только смещение до функции внутри класса, поэтому адрес, вероятно, относительно начала адреса экземпляра) метода (указатель на класс получается как обычно):
Код:

FunctionPtr=&MyCl::func1;
вызов (вызываю функцию с адресом FunctionPtr [здесь это func1] из экземпляра с адресом ParentInterface ):
Код:

(ParentInterface->*FunctionPtr)(0,0,0);

upd поправил код

genroelgvozo 25.08.2011 20:10

Ответ: Укозатель на метод класса
 
этот код работает? или это с++0x уже? я просто новый стандарт не знаю
а то как бы это получаются делегаты через обычный указатель (я думал что в си такое невозможно )
вот статья на хабре как сделать простой делегат на си++ http://habrahabr.ru/blogs/cpp/78299/

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

impersonalis 25.08.2011 21:08

Ответ: Укозатель на метод класса
 
Да, код работает на MSVC++ 6.0 (откуда [год разработки 6-ой сутдии] можно сделать вывод, что это не с++0x).
Повторю ещё раз ссылку на руководство по указателям на функции http://www.newty.de/fpt/index.html

Цитата:

Сообщение от genroelgvozo (Сообщение 200121)
UPD
У меня так не работает. Он говорит что функптр должен быть указатель на функцию, а если я его обьявляю как указатель на функцию, он пишет что он должен быть указатель на член))

Неправильно скопировал, прошу извинить. Ошибка вот здесь (теперь правильно):
Код:

(ParentInterface->*FunctionPtr)(0,0,0);
К сожалению, проверить сейчас не могу, но пример составлен из рабочего кода.

genroelgvozo 25.08.2011 21:54

Ответ: Укозатель на метод класса
 
Хм, интересно
и таким образом функцию, которая принимает метод и обьект, можно сделать шаблонной, чтоб отойти от типизации
и тогда мне опять не понятно, а нафига boost?

Dream 26.08.2011 01:58

Ответ: Укозатель на метод класса
 
по поводу указателей и вообще реализации делегатов на С++
http://www.rsdn.ru/article/cpp/delegates.xml

alcoSHoLiK 26.08.2011 02:21

Ответ: Укозатель на метод класса
 
Как вариант, можно написать функцию-обертку, которая сохранит указатель this. Получится некое подобие замыкания для частного случая.

Код:

int net_thread_wrapper(void *data, net *this = 0) {
    static net *that;
    if (this) {
        that = this;
        // больше ничего не делаем, чтобы не вызвать изменений в this
        return 0;
    }
    return that->thread(data);
}

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

Код:

net *instance = new net();
net_thread_wrapper(NULL, instance);
SDL_CreateThread(&net_thread_wrapper, &timeout); 

// ...

delete instance;

Наверняка понадобится каст, чтобы успокоить компилятор. На работоспособность этого подхода он не должен повлиять. Отпишись о результатах, пожалуйста.


Часовой пояс GMT +4, время: 03:47.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Перевод: zCarot