2015-05-23 3 views
1

Как я могу сделать двойной указатель на функцию класса и члена?Указатель на класс И указатель на метод

В принципе, у меня есть некоторые (довольно много) общие классы, принимающие указатели на функции, как это:

void Gen::regCallback(void (*callback)(void const *), void const * callbackData) 

и в классах, я часто либо функции, как этот

void Foo::doSomething(void const * instance) // this one is static 
{ 
    auto myself((Foo const *)instance); 
    myself->...do stuff... 
    myself->...do stuff... 
    myself->...do stuff... 
} 

или метод/функции близнецов

void Foo::doSomething(void const * instance) // this one is static 
{ 
    ((Foo const *)instance)->doSomething(); 
} 
void Foo::doSomething() const 
{ 
    ...do stuff... 
    ...do stuff... 
    ...do stuff... 
} 

Я хотел бы как-то уменьшить беспорядок в коде (по регистрации непосредственно членов), Я знаю вариант:

void Gen::regCallback(void (Foo::*callback)(void const *), Foo const * member); 

, но мне нужно сделать также типа класса (Foo), который будет принят в качестве параметра (т.е. Foo1, Foo2, FooTotallyDifferent)

По разным причинам я не могу использовать шаблон для типа класса, так

template <typedef T> 
class Gen 
{ 
    void regCallback(void (T::*callback)(void const *), T const * member) 
    { 
     ... 
    } 
} 

не вариант для меня

+1

Вы рассмотрели использование 'станд :: function' и лямбда-функции? они облегчают всю обратную связь. –

+0

@DavidHaim Хм ... Я не знал о std :: function, кажется правдоподобным, попытаюсь это сделать – chmirko

ответ

1

Похоже, что вы хотите, чтобы иметь возможность зарегистрировать любой вызываемый, который принимает нулевые аргументы и возвращает void. Поскольку, предположительно, вы будете хранить эти обратные вызовы где-то, вам также понадобится стирание типа - поскольку вы хотите иметь возможность звонить Foo::doSomething() и doSomethingElse() и даже Bar::someMethod(with, some, args) агностически. Для всего этого и более, есть std::function. В частности, в вашем случае, std::function<void()>.

Использование прост. A std::function<void()> может быть построен из любой функции, соответствующей этой сигнатуре. Вот пример, который добавляет несколько различных типов с правом отзыва на вектор одного std::function типа:

using Callback = std::function<void()>; 
std::vector<Callback> callbacks; 

void free() { std::cout << "free\n"; } 
void free(int arg) { std::cout << "free " << arg << "\n"; } 
struct Foo { 
    void something() const { std::cout << "Foo with " << i << "\n"; } 

    int i; 
}; 

callbacks.emplace_back(free); // normal function pointer 

Foo f; 
callbacks.emplace_back(std::bind(&Foo::something, f)); // member function bound to instance, copies f 

callbacks.emplace_back([]{ free(42); }); // lambda calling function with specific argument 

f.i = 64; 
callbacks.emplace_back([&]{ f.something(); }); // captures f 
f.i = 72; 

// call all of them 
for (auto fn : callbacks) { 
    fn(); 
} 

Это напечатает

free 
Foo with 42 
free 42 
Foo with 72 
+0

Я отмечаю это как ответ, Я просто не получаю: callbacks. emplace_back (std :: bind (& Foo :: something, i)); где «i» произошло от – chmirko

+0

i является переменной-членом foo – Boofhead

+0

@chmirko Typo, предполагалось быть 'f'. – Barry

Смежные вопросы