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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> 2 вида функций const и обычная. Как избежать дублирования кода? 
V
    Опции темы
Rapalex
Дата 10.8.2007, 12:00 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 732
Регистрация: 20.1.2006
Где: Украина -> Ник олаев

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



У одного класса есть 2 функции:
Код


CGsr* CProject::GetGsr(const CSourceType *poSourceType)
{
    for (INT_PTR i=0; i<m_arPtrGsr.GetSize(); i++)
    {
        CGsr *poGSR = m_arPtrGsr.GetAt(i);
        if (*poSourceType == *poGSR)
            return poGSR;
    }
    return NULL;
}

const CGsr* CProject::GetGsr(const CSourceType *poSourceType) const
{
    for (INT_PTR i=0; i<m_arPtrGsr.GetSize(); i++)
    {
        CGsr *poGSR = m_arPtrGsr.GetAt(i);
        if (*poSourceType == *poGSR)
            return poGSR;
    }
    return NULL;
}


Разница между ними только в том что одна из них константная. Когда это функции в одну строчку типа:
Код

INT_PTR CProject::AddGsr(Gsr::CGsr *poGsr)
    { return m_arPtrGsr.Add(poGsr); }

я спокоен, а как в таком случае можно избавится от дублирования кода?

Это сообщение отредактировал(а) Rapalex - 10.8.2007, 12:02


--------------------
In vitium ducit culpae fuga.
Желание избежать ошибки вовлекает в другую.
(Horatius)
PM ICQ   Вверх
Lazin
Дата 10.8.2007, 12:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

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



если есть возможность сделать ф-ю константной, то неконстантная обычно не нужна, так как константная будет работать и для неконстантных аргументов.  smile Ну и фраза млин. 
Короче константная канает везде а обычная не везде.

Это сообщение отредактировал(а) Lazin - 10.8.2007, 12:10
PM MAIL Skype GTalk   Вверх
Vyacheslav
Дата 10.8.2007, 12:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

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



Написать еще одну 
Код

const CGsr* CProject::InternalGetGsr(const CSourceType *poSourceType) const
{
   for (INT_PTR i=0; i<m_arPtrGsr.GetSize(); i++)
    {
        CGsr *poGSR = m_arPtrGsr.GetAt(i);
        if (*poSourceType == *poGSR)
            return poGSR;
    }
    return NULL;

}

CGsr* CProject::GetGsr(const CSourceType *poSourceType)
{
    return const_cast<CGsr*>( InternalGetGsr(poSourceType));
}

const CGsr* CProject::GetGsr(const CSourceType *poSourceType) const
{
   return InternalGetGsr(poSourceType);
}



PS Целесобразность присутствия в классе двух таких функций оставляем вне рамок  данного обсуждения smile


--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Lazin
Дата 10.8.2007, 13:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

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



Вообще нужно либо делать ф-ии константными везде где это можно, либо вообще их не использовать, но в этом случае константными объектами будет проблематично пользоваться. 
PM MAIL Skype GTalk   Вверх
Vyacheslav
Дата 10.8.2007, 14:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

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



В данном случае, насколько я понял, константность функции нужна, что бы иметь перeгрузку функций,  формально отличающихся только возращаемым типом 
Код

CGsr* GetGsr(const CSourceType *poSourceType);
const CGsr*GetGsr(const CSourceType *poSourceType) const

По стандарту такая перегрузка невозможи и для того чтобы это обойти, одна из фукций объявлена константной. Благо, код функции позволяет воспользоваться такой возможностью
При этом имеею смелость предположить, что автор топика несколько заблуждается по поводу того, в каких случаях будет вызываться та или иная функция smile . Заранее  извиняюсь, если мое предположение ошибочно



--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Rapalex
Дата 10.8.2007, 14:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 732
Регистрация: 20.1.2006
Где: Украина -> Ник олаев

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



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

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

Это сообщение отредактировал(а) Rapalex - 10.8.2007, 14:55


--------------------
In vitium ducit culpae fuga.
Желание избежать ошибки вовлекает в другую.
(Horatius)
PM ICQ   Вверх
Vyacheslav
Дата 10.8.2007, 15:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

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



Вот это в данной формулировке не совсем корректно
Цитата(Rapalex @  10.8.2007,  14:54 Найти цитируемый пост)
Vyacheslav, константная функция будут вызыватся если я работаю с константным указателем, а если указатель не константный, то вызовется не константная функция.

Все таки не с  константным указателем, а константным объектом. При этом не важно посредством чего к нему  обращаются:  посредством указателя, ссылки или  используют сам объект.
Я к тому, что в случае 
Код

CProject project;
//....
const CGsr* pGsr = project.GetGsr(poSourceType);  

вызовется неконстантный вариант

Код

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

А вот это , скажем так, понятно но не черезчур Вы себя контролируете? Константный или неконстантный объект - это уже известно на этапе компиляции, если объект  константный  а функции констатной нет, то  Вы сами можете написать 
Код

void SomeFuction (const CProject* project )
{
//...
const CGsr* pGsr = project->GetGsr(poSourceType); 
//...
}
 

И фиг Вам дальше компилятор позволят изменить pGsr
Единственное отличие, что в случае наличия константной функции Вас компилятор обругает, если Вы случайно ошибетесь и напишите
Код

void SomeFuction (const CProject* project )
{
//...
CGsr* pGsr = project->GetGsr(poSourceType); 
//...
}
 

Ради  одного этого такой огород городить? Неужели не в состоянии сами себя проконтролировать. Все таки это не тот  случай, когда в аналогичном случае в STL возвращается iterator и const_iterator ( const_iterator != const iterator  smile  )

Единственная польза от такого приема в конкретном случае мне видится только одна: если Вы любитель "многоуровневых" обращений
Код

project->GetGsr(poSourceType)->SomeFunction();


 




--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Ln78
Дата 10.8.2007, 16:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Хороший вопрос. Я сам раньше дублировал, сейчас попробовал несколько изменённый пример 
Vyacheslavа, получилось (по крайней мере в VS2005):
Код

class CZ 
{
    int z;
public:
    CZ() {z=111;}
    int& GetZ(void) 
    {
        return z;
    } 
    const inline int& GetZ(void) const
    {
        return (const_cast<CZ&> (*this)).GetZ();
    } 
};

void F(const CZ& cz1, CZ& cz2)
{
    int q = 2*cz1.GetZ();
    cz2.GetZ() = 13 + q;
//    cz1.GetZ() = 100; //Даёт ошибку компиляции, как, собственно, и хотели
}



Цитата(Vyacheslav @  10.8.2007,  15:51 Найти цитируемый пост)
Неужели ради  этого такой огород городить

ИМХО, часто стоит: например, для контейнеров, у которых перегружаются операторы [] для доступа к элементам это бывает очень полезно

Да, кстати, Rapalex, для соседнего топика: например, в книге Элджера варианты константных указателей и указателей на константу расписаны

Это сообщение отредактировал(а) Ln78 - 10.8.2007, 16:03
PM MAIL   Вверх
Vyacheslav
Дата 10.8.2007, 16:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

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



Цитата(Ln78 @  10.8.2007,  16:00 Найти цитируемый пост)
ИМХО, часто стоит: например, для контейнеров, у которых перегружаются операторы [] для доступа к элементам это бывает очень полезно

ЭЭЭ. Нельзя же разумную идею превращать в ее противоположность. Если бы это был оператор[], то я бы не имел ничего против, поскольку для оператор [] естественно использование типа  
Код

project[poSourceType] = cGsr;
project[poSourceType] .SomeFuction();

т. е. обращение через временную ссылку, константность которой можно задать только заранее
Тут довольно легко ошибиться, причем на автомате smile



--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Ln78
Дата 10.8.2007, 16:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Я имел в виду: основная идея - избежать дублирования фукнций (и операторов в том числе), а уж к чему её применить, это уже другой вопрос  smile 
PM MAIL   Вверх
Alek86
Дата 10.8.2007, 17:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

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



Vyacheslav, как я понимаю, это требуется (и у меня нередко требовалось) в случае, если нужно:

1)
CGsr* GetGsr(const CSourceType *poSourceType);

Получать указатель на внутренние данные с целью их изменения. (некрасиво, т.е. не по ООП'ному, но иногда важна именно скорость).

2)
const CGsr*GetGsr(const CSourceType *poSourceType) const;

Получать указатель на внутренние данные с целью их "чтения" в других константных функциях.

Ну, и еще можно не добавлять 3ю функцию, а вызвать в неконстантной константную через
((const CProject*) this)->...
Но это дело вкуса, как я понимаю....


Если я не прав, просьба не нервничать. smile

Это сообщение отредактировал(а) Alek86 - 10.8.2007, 22:31


--------------------
user posted image    user posted image
PM MAIL   Вверх
Rapalex
Дата 11.8.2007, 09:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 732
Регистрация: 20.1.2006
Где: Украина -> Ник олаев

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



Ln78, 
Цитата(Ln78 @  10.8.2007,  16:00 Найти цитируемый пост)
 для соседнего топика: например, в книге Элджера варианты константных указателей и указателей на константу расписаны

А можно полне название книги, чтоб погуглить смог  smile 

Alek86, полность согласен, особенно с 
Цитата(Alek86 @  10.8.2007,  17:43 Найти цитируемый пост)
Получать указатель на внутренние данные с целью их "чтения" в других константных функциях.




--------------------
In vitium ducit culpae fuga.
Желание избежать ошибки вовлекает в другую.
(Horatius)
PM ICQ   Вверх
Ln78
Дата 11.8.2007, 11:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Rapalex, книга из серии "Библиотека программиста", автор Джеф Элджер, название "С++". У меня только бумажная версия.
И кстати, почему согласен только с Alek86? В моём примере как раз это и приведено, так же, как и отсутствие промежуточной функции.  smile  Там просто не указатели а ссылки, но это дело не меняет.
PM MAIL   Вверх
Alek86
Дата 11.8.2007, 11:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

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



Ln78, в твоем примере

Код

    const inline int& GetZ(void) const
    {
        return (const_cast<CZ&> (*this)).GetZ();
    } 


константная функция вызывает неконстантную?


--------------------
user posted image    user posted image
PM MAIL   Вверх
Ln78
Дата 11.8.2007, 14:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Alek86, а сам как думаешь? Скопируй пример, дополни вызовом функции F и посмотри под отладчиком, кто что вызывает. Ну а сколько в моём примере функций вроде и так видно. Чтобы не повышать мелкодисперсность оксида двухатомного водорода механическим путём (воду в ступе толочь) вряд ли нужно обсуждать это ещё на несколько постов.
PM MAIL   Вверх
Страницы: (3) Все [1] 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

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

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

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

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


 




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


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

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