Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Указатель на функцию или отдельно функция? 
:(
    Опции темы
xTr1m
Дата 26.7.2012, 17:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 692
Регистрация: 9.2.2005
Где: Москва

Репутация: 1
Всего: 1



Имеем такую функцию. От каждого элемента получить дочерний.

Код

void CSomeClass::GetChildItems( const vector<Item*> &allItems, vector<Item*> &childItems)
{
   for(unsigned int i=0; i<allItems.size(); ++i)
   {
        Item *childItem = allItems[i].GetChild();
        if(childItem != 0)
            childItems.push_back(childItem);
    }
}


теперь мне нужно в некоторых местах получить дочерние элементы, но определенного типа (применив какой-нибудь фильтр). Тут два варианта (как я вижу).
1) Сначала берем все дочерние, потом отфильтровываем

Код

// в одном месте напишем так
GetChildItems(allitems, childItems);
FilterByStatus(childitems);
...
// в другом так
GetChildItems(allitems, childItems);
FilterByCreationTime(childitems);


2) Отфильтруем элементы сразу в функции "Get..."
Код

typedef bool(CSomeClass::*filterFunction)(Item*) const;

void CSomeClass::GetChildItems( const vector<Item*> &allItems, vector<Item*> &childItems, filterFunction func)
{
   for(unsigned int i=0; i<allItems.size(); ++i)
   {
        Item *childItem = allItems[i].GetChild();
        if(childItem != 0 && (0 == func || (func && (this->*func)(childItem))))
            childItems.push_back(childItem);
    }
}


Вопрос в том, что лучше. То есть в первом варианте у нас гораздо меньше вызовов именно функций, но как то не ООП, в отличие от второго варианта. 
А может я слишком заморачиваюсь и разницы особой нет?

Это сообщение отредактировал(а) xTr1m - 26.7.2012, 17:40
PM MAIL WWW ICQ   Вверх
Amp
Дата 26.7.2012, 17:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 886
Регистрация: 17.2.2009

Репутация: 3
Всего: 17



Первый вариант фильтрации просто памяти больше будет потреблять на больших коллекциях. Но идеологически, в разрезе проектирования API, наверное более предпочтителен. Ну а во втором варианте я бы передавал какие-нибудь std::function/lambda, нежели голый указатель на функцию.

Это сообщение отредактировал(а) Amp - 26.7.2012, 17:54
PM MAIL   Вверх
xTr1m
Дата 26.7.2012, 17:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 692
Регистрация: 9.2.2005
Где: Москва

Репутация: 1
Всего: 1



Ну передается все по ссылкам, поэтому никаких копирований не предвидеться. Единственное в первом варианте нужно пройтись два раза по этой самой коллекции. 
А чем все же именно предпочтительнее? =))
PM MAIL WWW ICQ   Вверх
Amp
Дата 26.7.2012, 18:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 886
Регистрация: 17.2.2009

Репутация: 3
Всего: 17



Да как хочешь smile
PM MAIL   Вверх
xTr1m
Дата 26.7.2012, 18:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 692
Регистрация: 9.2.2005
Где: Москва

Репутация: 1
Всего: 1



Хорошо скажу так. Мне больше нравится второй вариант, однако его использование (указатели на функции + все же многократный вызов этой самой функции) в глазах начальства может выглядеть как "а зачем оно так нужно, если можно по-старинке, где все понятно и просто". Вот я и собираю аргументы.
PM MAIL WWW ICQ   Вверх
borisbn
Дата 26.7.2012, 18:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Мне второй вариант больше нравится... Обидно будет, если в коллекции, допустим, миллион элементов, а функция фильтрации оставит 2....
Кстати, функцию фильтрации, возможно, можно сделать универсальной. Не FilterByStatus или FilterByCreationTime, а
Код

template< class FieldType, FieldType Item::*FieldPtr >
struct FilterBy {
    FilterBy( const FieldType & value ) : m_value( value ) {}

   bool operator()( Item * item ) {
    if ( item->*FieldPtr == m_value ) {
        return true;
    }
private:
    const FieldType & m_value;
}
...
template< class FilterFunc >
void CSomeClass::GetChildItems( const vector<Item*> &allItems, vector<Item*> &childItems, FilterFunc func )
{
  for(unsigned int i=0; i<allItems.size(); ++i)
   {
        Item *childItem = allItems[i].GetChild();
        if ( childItem != 0 && func( childItem ) )
            childItems.push_back(childItem);
    }
}
...
// вызов
GetChildItems( allItems, childItems, FilterBy< int, &Item::status >( 0x42 ) ); 
GetChildItems( allItems, childItems, FilterBy< Time, &Item::creationTime >( Time( "21.12.2012" ) ); 


Добавлено @ 18:18
а добавив функцию NoFilter, получишь свою изначальную (не фильтрующую) функцию
Код

bool NoFilter( Item * ) {
    return true;
}
GetChildItems( allItems, childItems, NoFilter ); 


Это сообщение отредактировал(а) borisbn - 26.7.2012, 18:19


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Result
Дата 26.7.2012, 18:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 52
Регистрация: 15.5.2011

Репутация: 2
Всего: 5



Имхо, красивее посмотреть на компоновщик+итератор. 
Анкл Боб рекомендовал разбивать на функции выполняющие одно логическое действие, ну 
или отображать перечень в имени метода GetChildItemByFilter.
По поводу аргументов начальству, так это смотря что им нужно, костыли или архитектура.
PM   Вверх
borisbn
Дата 26.7.2012, 21:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



> красивее посмотреть на компоновщик+итератор.
Это как? Можно продемонстрировать кодом?


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
xTr1m
Дата 27.7.2012, 08:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 692
Регистрация: 9.2.2005
Где: Москва

Репутация: 1
Всего: 1



borisbn, за шаблонный вариант спасибо, но боюсь одно слово шаблон вызовет косые взгляды ан меня =))
Result, по поводу архитектуры. Вариант с шаблоном действительно явный пример архитектурного решения. В изначальном же варианте я не вижу явных аргументов, кроме как "это архитектура лучше", вот и хочу узнать чем. Может есть какой-нибудь сценарий развития, при котором в будущем мой 2ой вариант легче модернизировать, чем первый?
PM MAIL WWW ICQ   Вверх
korian
Дата 27.7.2012, 09:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 651
Регистрация: 8.3.2008
Где: Украина, Харьков

Репутация: 3
Всего: 17



Из того как я понял задачу, я считаю, что должны существовать обе функции.
Там, где нужны все child - дергаем одну, там где фильтрование - вторую.
Ну и второй вариант должен выглядеть примерно следующим образом (без всяких проверок и привязок):
Код

void CSomeClass::GetChildItems( const vector<Item*> &allItems, vector<Item*> &childItems, filterFunction func)
{
   for(unsigned int i=0; i<allItems.size(); ++i)
   {
        Item *childItem = allItems[i].GetChild();
        if(childItem != 0 && func(childItem))
            childItems.push_back(childItem);
    }
}


Можно сказать, что это копи-паст и тд. Но это нормальный копи-паст, потому что функции делают разное.
Пример такого подхода можно считать функцию erase в std::vector.

iterator erase ( iterator first, iterator last );
iterator erase ( iterator position );

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

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

Аргументы:
Имея только одну функцию и реализацию по первому варианту - мы имеем преджевременную писсимизацию (тратим ОЗУ, чего можно не делать)
Имея только одну функцию и реализацию по второму варианту - ме имеем ту же преджевременную писсимизацию (тратим CPU на проверки, чего можно не делать)


Это сообщение отредактировал(а) korian - 27.7.2012, 09:09
PM   Вверх
Result
Дата 29.7.2012, 13:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 52
Регистрация: 15.5.2011

Репутация: 2
Всего: 5



Цитата(borisbn @ 26.7.2012,  21:21)
Это как? Можно продемонстрировать кодом?

Вот примерчик накидал http://liveworkspace.org/ 
Правда абстрактный пример не очень нагляден  smile 
Интересное представляет main.
PM   Вверх
mes
Дата 29.7.2012, 22:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(korian @  27.7.2012,  08:08 Найти цитируемый пост)
впринципе, можно было бы обойтись только первой функцией. она полностью покрывает все потребности.
но удобство использования и возможность оптимизации при удалении одного элемента, заставляют иметь вторую.

эта потребность возникает вследствии "ограничения" доступа к древу обьектов функцией ГетЧайлдс.. Если предоставить константый доступ к ссылке на ветку, то можно будет применять стандартные алгоритмы.. Вобщем начинать надо не с вопроса какой сделать функцию, а с того как наиболее удобным образом представить данные... 

Это сообщение отредактировал(а) mes - 29.7.2012, 22:58


--------------------
PM MAIL WWW   Вверх
korian
Дата 30.7.2012, 15:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 651
Регистрация: 8.3.2008
Где: Украина, Харьков

Репутация: 3
Всего: 17



Цитата(mes @  29.7.2012,  21:57 Найти цитируемый пост)
доступа к древу обьектов функцией ГетЧайлдс

Так это все-таки дерево? У меня как бы была мысль, но я не увидел никакого кода обхода дерева.

PM   Вверх
mes
Дата 30.7.2012, 22:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



список - частный случай древа smile


--------------------
PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1337 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.