Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

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

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

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 13.08.2017, 16:36   #1
ACE Valery
Сама себе режиссер
Старожил
 
Аватар для ACE Valery
 
Регистрация: 27.04.2007
Сообщений: 3,365
По умолчанию Передача функции-члена класса В коллбеком в класс А

Всем привет. Спецы С++, помогите, плиз, совсем запуталась.
Есть функция (А::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, 17:00   #2
Croessmah
Вредный кошак
Участник клуба
 
Аватар для Croessmah
 
Регистрация: 14.10.2012
Сообщений: 1,159
По умолчанию

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

Какая конечная цель?
Croessmah вне форума Ответить с цитированием
Старый 13.08.2017, 17:46   #3
ACE Valery
Сама себе режиссер
Старожил
 
Аватар для ACE Valery
 
Регистрация: 27.04.2007
Сообщений: 3,365
По умолчанию

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

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

Цитата:
Сообщение от 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, 18:27   #5
Croessmah
Вредный кошак
Участник клуба
 
Аватар для Croessmah
 
Регистрация: 14.10.2012
Сообщений: 1,159
По умолчанию

Цитата:
Конечная цель "чтоб работало" не катит?
Код:
int main() {}
Должно заработать, проверьте.
Croessmah вне форума Ответить с цитированием
Старый 13.08.2017, 19:46   #6
ACE Valery
Сама себе режиссер
Старожил
 
Аватар для ACE Valery
 
Регистрация: 27.04.2007
Сообщений: 3,365
По умолчанию

_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 в 19:49.
ACE Valery вне форума Ответить с цитированием
Старый 13.08.2017, 21:36   #7
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

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

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

ну так...

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

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

однако, в вашем варианте:
Код:
a.boo(&friend_foo, this);
почему то функция стала принимать два аргумента.
в то время, как в изначальном варианте:
Код:
void boo(my_func func)
функция принимала только 1 аргумент.
и вы сами писали,
что этот класс менять нельзя.
_Bers вне форума Ответить с цитированием
Старый 13.08.2017, 23:37   #8
ACE Valery
Сама себе режиссер
Старожил
 
Аватар для ACE Valery
 
Регистрация: 27.04.2007
Сообщений: 3,365
По умолчанию

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

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

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

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


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Передача метода одного класса как параметр функции другого KemanSR Общие вопросы C/C++ 4 22.07.2015 21:20
Передача члена класса в другой класс Cerg1580 Общие вопросы C/C++ 0 20.12.2014 13: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 17:21