Форум программистов
Реклама:
Гарантия безопасности сети с UTM-системой ИКС.
Защита ПД, межсетевой экран, контроль доступа, фильтрация трафика, система предотвращения вторжений.
Контакты: о проблемах с регистрацией, почтой и по другим вопросам пишите сюда - alarforum@yandex.ru, проверяйте папку спам! Обязательно пройдите активизацию e-mail.

Вернуться   Форум программистов > C++ > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Ответ
 
Опции темы
Старый 13.08.2017, 17:36   #1
ACE Valery
С++ admirer
СуперМодератор
 
Аватар для ACE Valery
 
Регистрация: 27.04.2007
Адрес: Украина
Сообщений: 2,856
Репутация: 2587
По умолчанию Передача функции-члена класса В коллбеком в класс А

Всем привет. Спецы С++, помогите, плиз, совсем запуталась.
Есть функция (А::boo), в нее нужно передать другую функцию, определенную тайпдефом ( typedef void(*my_func)(void*) ). В классе B есть функция foo ( void foo(void * param) ), которую я и пытаюсь передать параметром, но у меня не получается (ошибки выделены в коде). Гугл в примерах использования подобной конструкции выдает практически такой же код. Подскажите, что я делаю не так?

В классе А ничего менять нельзя, если что.

Код:

class A
{
public:
	typedef void(*my_func)(void*);

	void boo(my_func func)
	{
		std::cout << "boo";
	}
}

class B
{
public:
        A a;

	void foo(void * param) 
	{
		std::cout << "foo";
	}

	void main()
	{
                //пыталась передавать разными способами, но результат один:
		//argument of type "void (B::*)(void *param)" is incompatible with parameter of type "A::my_func"
		a.boo(&foo);
		a.boo(foo);

		//a value of type "void (B::*)(void *param)" cannot be used to initialize an entity of type "A::my_func"
		A::my_func test = &foo;
		a.boo(test);
	}
}

__________________
Если я вас напрягаю или раздражаю, вы всегда можете забиться в угол и поплакать
ACE Valery на форуме   Ответить с цитированием
Старый 13.08.2017, 18:00   #2
Croessmah
Вредный кошак
Профессионал
 
Аватар для Croessmah
 
Регистрация: 14.10.2012
Адрес: г. Инза
Сообщений: 1,074
Репутация: 362
По умолчанию

Указатель на функцию-член - это не указатель.

Какая конечная цель?
Croessmah на форуме   Ответить с цитированием
Старый 13.08.2017, 18:46   #3
ACE Valery
С++ admirer
СуперМодератор
 
Аватар для ACE Valery
 
Регистрация: 27.04.2007
Адрес: Украина
Сообщений: 2,856
Репутация: 2587
По умолчанию

Конечная цель "чтоб работало" не катит?
Мне в функцию boo надо передать коллбек из моего основного класса. Разумеется, в вышеописанном коде я упростила реализацию функции boo. На самом деле она производит какие-то действия, а в конце выполняет переданную в параметр функцию.

Цитата:
Указатель на функцию-член - это не указатель
А что это?
__________________
Если я вас напрягаю или раздражаю, вы всегда можете забиться в угол и поплакать
ACE Valery на форуме   Ответить с цитированием
Старый 13.08.2017, 19:11   #4
_Bers
Профессионал
 
Регистрация: 16.12.2011
Адрес: Москва
Сообщений: 2,004
Репутация: 814
По умолчанию

Цитата:
Сообщение от ACE Valery Посмотреть сообщение
что я делаю не так?
вот это:
Код:

void B::foo(void * param)

не просто обычная функция.

это - функция член класса.

1.
сам по себе тип "функции-члена" отличается от типа "функция"
Код:

typedef void B::method(void *);
typedef void func(void *);

функция член хранит в собственном типе информацию
об имени класса, членом которого она является.

2.
что бы выполнить запуск функции-члена по указателю на функцию-член,
необходим объект для которого функция-член будет запущена.


мы не сможем выполнить действие "открыть дверь автомобиля",
если не укажем для какого именно автомобиля нужно открыть дверь.

"откройте мне дверь, но я вам не скажу от какого автомобиля" - звучит как бред.

3.
если класс A нельзя модифицировать,
тогда то, что вы пытаетесь совершить - более чем странно и не логично.

а само решение невозможно.
поскольку противоречит здравому смыслу.

4.
если бы класс А можно было модифицировать,
тогда ваше желание можно было бы легко удовлетворить:

http://rextester.com/QCRXC10291

Код:

#include <iostream>
#include <functional>

class A
{
public:
	typedef std::function<void(void*)>
        my_func;

	void boo(const my_func& func)
	{
		std::cout << "execute: ";
        func(nullptr);
	}
};

class B
{
public:
    A a;

	void foo(void * param) 
	{
		std::cout << "foo: param = " << param << '\n';
	}

	void main()
	{
        // вариант с лямбдой
        a.boo([this](void* param){ this->foo(param); } );

        
        using namespace std::placeholders;
        
        // вариант с байндом
        a.boo( std::bind(&B::foo, this, _1) );

        // обратите внимание: 
        // мы указываем что именно хотим запустить (&B::foo)
        // для какого объекта (this)
        // с каким аргументом (_1 - означает, что с каким то одним, 
        // который будет известен позже, непосредственно при запуске)
        A::my_func test = std::bind(&B::foo, this, _1);
        
		a.boo(test);
	}
};


int main()
{
    B obj;
    obj.main();
}

_Bers на форуме   Ответить с цитированием
Старый 13.08.2017, 19:27   #5
Croessmah
Вредный кошак
Профессионал
 
Аватар для Croessmah
 
Регистрация: 14.10.2012
Адрес: г. Инза
Сообщений: 1,074
Репутация: 362
По умолчанию

Цитата:
Конечная цель "чтоб работало" не катит?
Код:

int main() {}

Должно заработать, проверьте.
Croessmah на форуме   Ответить с цитированием
Старый 13.08.2017, 20:46   #6
ACE Valery
С++ admirer
СуперМодератор
 
Аватар для ACE Valery
 
Регистрация: 27.04.2007
Адрес: Украина
Сообщений: 2,856
Репутация: 2587
По умолчанию

_Bers, спасибо большое за информацию. Не думала, что в С++ так все может быть сложно с этим. Потому как в AS3 можно без проблем передать любую функцию в любой класс.

Что касается класса А, то переделать я его действительно не могу, потому что он не мой, а движка. И документации/примеров использования у меня нет, поэтому я посчитала, что все должно быть просто. Трудности перевода, так сказать...

И не использовать тот класс я тоже не могу, так как если писать похожий свой, то достаточно много писанины.

Поэтому я выкрутилась. Не могу сказать, что горжусь этим, но лучше, чем ничего.

Код:

class B
{
public:
        A a;

	firend void friend_foo(void * param) 
	{
		static_cast<B*>(param)->foo();
	}

        void foo() 
	{
		std::cout << "foo";
	}

	void main()
	{
		a.boo(&friend_foo, this);		
	}
}

__________________
Если я вас напрягаю или раздражаю, вы всегда можете забиться в угол и поплакать

Последний раз редактировалось ACE Valery; 13.08.2017 в 20:49.
ACE Valery на форуме   Ответить с цитированием
Старый 13.08.2017, 22:36   #7
_Bers
Профессионал
 
Регистрация: 16.12.2011
Адрес: Москва
Сообщений: 2,004
Репутация: 814
По умолчанию

Цитата:
Сообщение от ACE Valery Посмотреть сообщение
Потому как в AS3 можно без проблем передать любую функцию в любой класс.
ну так и на с++ тоже можно легко передавать
и функции, и функции члены.

просто в вашем случае,
ваш класс хочет принимать только обычные функции.
и вы сами пишите: изменять его нельзя.

ну так...

Цитата:
Сообщение от ACE Valery Посмотреть сообщение
Поэтому я выкрутилась. Не могу сказать, что горжусь этим, но лучше, чем ничего.
вполне себе жизнеспособный способ.
очень распространен в мире языка си

функция получает void* param
то бишь, передать можно все что угодно.

однако, в вашем варианте:
Код:

a.boo(&friend_foo, this);

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

void boo(my_func func)

функция принимала только 1 аргумент.
и вы сами писали,
что этот класс менять нельзя.
_Bers на форуме   Ответить с цитированием
Старый 14.08.2017, 00:37   #8
ACE Valery
С++ admirer
СуперМодератор
 
Аватар для ACE Valery
 
Регистрация: 27.04.2007
Адрес: Украина
Сообщений: 2,856
Репутация: 2587
По умолчанию

Моя вина, признаЮсь. Я слишком сильно упростила класс А для форума. Там изначально принимался параметр. Просто я думала, что дело именно в моем синтаксисе, и оставила только те вещи, которые, мне казалось, важны для понимания проблемы.
__________________
Если я вас напрягаю или раздражаю, вы всегда можете забиться в угол и поплакать
ACE Valery на форуме   Ответить с цитированием
Старый 14.08.2017, 07:06   #9
Croessmah
Вредный кошак
Профессионал
 
Аватар для Croessmah
 
Регистрация: 14.10.2012
Адрес: г. Инза
Сообщений: 1,074
Репутация: 362
По умолчанию

Цитата:
Сообщение от ACE Valery Посмотреть сообщение
Поэтому я выкрутилась.
Если функция boo принимает два параметра,
то можно передать указатель на статическую
функцию класса, вместо дружественной.
Croessmah на форуме   Ответить с цитированием
Старый 14.08.2017, 08:33   #10
waleri
Профессионал
 
Регистрация: 13.07.2012
Адрес: Нижний Новгород
Сообщений: 5,013
Репутация: 1482
По умолчанию

Прочитайте про std::function и std::bind.
Так же поищите инфу по сочетанию "delegate C++"
Ну а если уж так строго и нельзя менять А тогда придется в куче выделять структуру, в которой будет std::function и передавать как параметр для вызова колбэка.

Последний раз редактировалось waleri; 14.08.2017 в 08:38.
waleri вне форума   Ответить с цитированием
Ответ



Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Передача метода одного класса как параметр функции другого KemanSR Общие вопросы C/C++ 4 22.07.2015 22:20
Передача члена класса в другой класс Cerg1580 Общие вопросы C/C++ 0 20.12.2014 14:13
передача функции в конструктор класса Kukurudza Общие вопросы C/C++ 6 04.12.2011 08:31
передача типов из класса в класс badmfck Общие вопросы Delphi 10 24.05.2010 12:31
Передача ссылки в функцию класса на данный класс Impuls1989 Общие вопросы C/C++ 17 09.01.2010 18:21




23:26.


Powered by vBulletin® Version 3.8.8 Beta 2
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.

купить трафик


как улучшить посещаемость, а также решения по монетизации сайтов, видео и приложений

RusProfile.ru


Справочник российских юридических лиц и организаций.
Проекты отопления, пеллетные котлы, бойлеры, радиаторы
интернет магазин respective.ru