[C++] указатель на функцию

Sanjaz

Как передать метод класса в качестве аргумета функции?
Например:

class A
{
int memb(int a);
}

void function( int(*funcint) );
Нужно что-то вроде

function(&A::memb);

maggi14

Когда ж вы научитесь юзать поиск?

rosali

Когда ж вы научитесь нормально на С++ программировать? НИКОГДА не нужно передавать никуда никакой указатель на метод. Это глупость. Да, есть вот в С++ такая глупость, ну и что? Обязательно надо каждой глупостью воспользоваться?

Julie16

Почему? Иногда это бывает полезным...

rosali

Иногда это бывает полезным...
Да? А ты не замечал, что каждый раз как сделаешь что-нибудь на этих долбаных member-pointer-ах, то обязательно через пару месяцев все равно приходится переделывать в виртуальные методы? Ну не продуманая эта идея, что ж тут поделаешь? C#-ные делегаты еще куда ни шло, а member-pointer-ы повторяю глупость. Их в язык добавили не потому что они нужны кому-то, а потому что было легко добавить. Такая же глупость как скажем f(...) тоже скажешь иногда полезно бывает?

Julie16

Могу привести реальный пример когда такая штука очень полезна. Допустим у меня есть некий класс, который делает некую штуку. Причем данные для него парсятся, а самим методы вызываются редко. Что делаю я:
1) Создаю 2 метода:
doInternal
{
parse;
doInternalParsed;
d_method=dInternalParsed;
}
doInternalParsed
{
blabla
}
2) Иницифлизирую в конструкторе d_method методом doInternal
3) Создаю основной метод
do
{
(*d_method;
}
Получаю значительный выигрыш, так как данные парсятся только тогда когда в первый раз вызывается метод. Причем без всяких проверок, что важно.
А теперь если мне надо скопировать этот класс, то мне придется передавать и этот метод. Вот так вот.

rosali

И что тебе мешает просто написать

do {
if(!is_parsed) {
parse;
is_parsed = true;
}
doInternalParsed;
}
Эстетизм не позволяет? Напоминаю, что member-pointer бывает и виртуальным и нет, поэтому мой if конечно же эффективнее...
PS. убил ты меня своим Реальным примером...

Julie16

Почему же эффективнее? Лишнее вычисление + jmp && conditional jmp.
Могу еще пример: у меня есть алгоритм, для которого есть 5 разных сортировок. Их надо циклически менять, а потом применять.
std::sort( begin end sort_funcs[ i ] ); i = (i + 1) % 5; Это у меня. В классе есть 5 методов, они объединены в массив sort_funcs. Как это сделаешь ты?

rosali

Кстати, заглянем на шаг вперед. Вот допустим твоя программа развивается, и ты пришел к выводу, что запускать parse нужно не только вначале, но и при некотором условии is_dirty я в своей программе исправляю одну строчку
 if(!is_parsed || is_dirty 
а ты? Нет, ты не можешь написать
 
doInternalParsed {
if(is_dirty {
parse;
}
...
}
это противоречит предыдущему эстетизму. Вместо этого ты изучаешь тело is_dirty ищешь места, где он может измениться и вставляешь туда d_method = doInternal. Так логично. Но еще через пару таких итераций...

Julie16

При чем тут эстетизм? Здоровый прагматизм

Dasar

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

Julie16

И данные между ними тоже шарить?

Dasar

Зачем?
Передавай this и сделай их friend-ами.

Julie16

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

rosali

Почему же эффективнее? Лишнее вычисление + jmp && conditional jmp.
Было. При вызове по member-pointer-у компилятор генерирует развилку, этот mp указывает на виртуальный метод или нет. Не говоря уже о том что indirect jump всегда сбрасывает конвейер, а для conditional jump есть prediction.
std::sort( begin end sort_funcs[ i ] );
Обман? тебе нужен bind(sort_funcs[ i ], this) или что-то типа того, разве нет?
В классе есть 5 методов, они объединены в массив sort_funcs. Как это сделаешь ты?
Интерфейс, обертка над ним, определяющая operator массив из таких оберток. А что, разве это действительно логично, что все эти алгоритмы сортировки своим контекстом имеют один и тот же объект? Это разве не может со временем измениться? Или ты будешь заводить в классе поле, как только оно нужно какому-то одному из сортировщиков?
Нет, я согласен, что всякие там mem_fun, boost::bind и т.п. написаны на member-pointer-ах, но это же совсем другое...

Julie16

Согласен, обман. Но только с виду. Оптимизирующий компилятор уберет эти лишние обертки нараз.

rosali

Вобщем так. Если важна скорость работы - пишем пять раз sort и не паримся. Если важна простота развития программы - тогда интерфейсы. А member-pointer-ы как всегда сосут

Julie16

5 раз sort нельзя. Так как эта хрень крутится в цикле.

Julie16

В данном случае сосут интерфейсы. Они менее локальны и поэтому менее понятны.

rosali

Нет, ну если написать

vector<boost::function2<int,int> > sort_funcs;
sort_funcs.push_back(boost::bind(MyClass::sort_func1, this;
sort_funcs.push_back(boost::bind(MyClass::sort_func2, this;
...
То ты этих интерфейсов и не заметишь, при этом та гибкость, которую задумал я но не задумал ты, останется. Потому что я пишу this в момент инициализации sort_funcs, и смогу заменить его на that, а ты пишешь (ну, я за тебя пишу, ты-то обманываешь ) this при вызове sort, так что поменять некоторые this на that не можешь. Имеется в виду что that - ко всему прочему еще и объект другого класса.

Julie16

Мне не нужна такая гибкость. Была бы нужна - я бы именно так и делал. Я утверждаю что указатели на члены бывают полезны. И я кажется добился своей цели - ты уже с этим почти не споришь. Я же не говорю что это лучшее решение. Они оба имеют право на существование. Это дело вкуса каждого

rosali


Так как эта хрень крутится в цикле.
Ну и что, все ради скорости, ни перед чем не останавливаемся!

for(;;) {
if(enough break;
sort(x.begin x.end func1);
if(enough break;
sort(x.begin x.end func2);
if(enough break;
sort(x.begin x.end func3);
if(enough break;
sort(x.begin x.end func4);
if(enough break;
sort(x.begin x.end func5);
}
Это место программы не собираемся развивать? Тогда не вижу препятствий - написал забыл.

Julie16

Ифов много... Медленно

rosali

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

Julie16

А мое дело отказаться
Оставить комментарий
Имя или ник:
Комментарий: