[C++] указатель на функцию
Когда ж вы научитесь юзать поиск?
Когда ж вы научитесь нормально на С++ программировать? НИКОГДА не нужно передавать никуда никакой указатель на метод. Это глупость. Да, есть вот в С++ такая глупость, ну и что? Обязательно надо каждой глупостью воспользоваться?
Почему? Иногда это бывает полезным...
Иногда это бывает полезным...Да? А ты не замечал, что каждый раз как сделаешь что-нибудь на этих долбаных member-pointer-ах, то обязательно через пару месяцев все равно приходится переделывать в виртуальные методы? Ну не продуманая эта идея, что ж тут поделаешь? C#-ные делегаты еще куда ни шло, а member-pointer-ы повторяю глупость. Их в язык добавили не потому что они нужны кому-то, а потому что было легко добавить. Такая же глупость как скажем f(...) тоже скажешь иногда полезно бывает?
1) Создаю 2 метода:
doInternal
{
parse;
doInternalParsed;
d_method=dInternalParsed;
}
doInternalParsed
{
blabla
}
2) Иницифлизирую в конструкторе d_method методом doInternal
3) Создаю основной метод
do
{
(*d_method;
}
Получаю значительный выигрыш, так как данные парсятся только тогда когда в первый раз вызывается метод. Причем без всяких проверок, что важно.
А теперь если мне надо скопировать этот класс, то мне придется передавать и этот метод. Вот так вот.
Эстетизм не позволяет? Напоминаю, что member-pointer бывает и виртуальным и нет, поэтому мой if конечно же эффективнее...
do {
if(!is_parsed) {
parse;
is_parsed = true;
}
doInternalParsed;
}
PS. убил ты меня своим Реальным примером...
Могу еще пример: у меня есть алгоритм, для которого есть 5 разных сортировок. Их надо циклически менять, а потом применять.
std::sort( begin end sort_funcs[ i ] ); i = (i + 1) % 5; Это у меня. В классе есть 5 методов, они объединены в массив sort_funcs. Как это сделаешь ты?
if(!is_parsed || is_dirtyа ты? Нет, ты не можешь написать
это противоречит предыдущему эстетизму. Вместо этого ты изучаешь тело is_dirty ищешь места, где он может измениться и вставляешь туда d_method = doInternal. Так логично. Но еще через пару таких итераций...
doInternalParsed {
if(is_dirty {
parse;
}
...
}
При чем тут эстетизм? Здоровый прагматизм
имхо, через набор классов с виртуальными функциями понятнее будет.
И данные между ними тоже шарить?
Передавай this и сделай их friend-ами.
Ужос. Вот это точно неэстетично Хотя я и согласен что такой подход имеет право на существование, но он ничуть не лучше. И мне не нравится. Хотя он может быть полезен если нужно будет уметь задавать сортировки извне...
Почему же эффективнее? Лишнее вычисление + 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-ах, но это же совсем другое...
Согласен, обман. Но только с виду. Оптимизирующий компилятор уберет эти лишние обертки нараз.
Вобщем так. Если важна скорость работы - пишем пять раз sort и не паримся. Если важна простота развития программы - тогда интерфейсы. А member-pointer-ы как всегда сосут
5 раз sort нельзя. Так как эта хрень крутится в цикле.
В данном случае сосут интерфейсы. Они менее локальны и поэтому менее понятны.
То ты этих интерфейсов и не заметишь, при этом та гибкость, которую задумал я но не задумал ты, останется. Потому что я пишу this в момент инициализации sort_funcs, и смогу заменить его на that, а ты пишешь (ну, я за тебя пишу, ты-то обманываешь ) this при вызове sort, так что поменять некоторые this на that не можешь. Имеется в виду что that - ко всему прочему еще и объект другого класса.
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;
...
Мне не нужна такая гибкость. Была бы нужна - я бы именно так и делал. Я утверждаю что указатели на члены бывают полезны. И я кажется добился своей цели - ты уже с этим почти не споришь. Я же не говорю что это лучшее решение. Они оба имеют право на существование. Это дело вкуса каждого
Ну и что, все ради скорости, ни перед чем не останавливаемся!
Так как эта хрень крутится в цикле.
Это место программы не собираемся развивать? Тогда не вижу препятствий - написал забыл.
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);
}
Ифов много... Медленно
Я утверждаю что указатели на члены бывают полезны.Да пользуйся на здоровье, мое дело предупредить
А мое дело отказаться
Оставить комментарий
Sanjaz
Как передать метод класса в качестве аргумета функции?Например:
Нужно что-то вроде