Д. Стефенс - C++. Сборник рецептов

Тут можно читать онлайн Д. Стефенс - C++. Сборник рецептов - бесплатно полную версию книги (целиком) без сокращений. Жанр: comp-programming, издательство КУДИЦ-ПРЕСС, год 2007. Здесь Вы можете читать полную версию (весь текст) онлайн без регистрации и SMS на сайте лучшей интернет библиотеки ЛибКинг или прочесть краткое содержание (суть), предисловие и аннотацию. Так же сможете купить и скачать торрент в электронном формате fb2, найти и слушать аудиокнигу на русском языке или узнать сколько частей в серии и всего страниц в публикации. Читателям доступно смотреть обложку, картинки, описание и отзывы (комментарии) о произведении.
  • Название:
    C++. Сборник рецептов
  • Автор:
  • Жанр:
  • Издательство:
    КУДИЦ-ПРЕСС
  • Год:
    2007
  • Город:
    Москва
  • ISBN:
    5-91136-030-6
  • Рейтинг:
    3.9/5. Голосов: 101
  • Избранное:
    Добавить в избранное
  • Отзывы:
  • Ваша оценка:
    • 80
    • 1
    • 2
    • 3
    • 4
    • 5

Д. Стефенс - C++. Сборник рецептов краткое содержание

C++. Сборник рецептов - описание и краткое содержание, автор Д. Стефенс, читайте бесплатно онлайн на сайте электронной библиотеки LibKing.Ru

Данная книга написана экспертами по C++ и содержит готовые рецепты решения каждодневных задач для программистов на С++. Один из авторов является создателем библиотеки Boost Iostreams и нескольких других библиотек C++ с открытым исходным кодом. В книге затрагивается множество тем, вот лишь некоторые из них: работа с датой и временем; потоковый ввод/вывод; обработка исключений; работа с классами и объектами; сборка приложений; синтаксический анализ XML-документов; программирование математических задач. Читатель сможет использовать готовые решения, а сэкономленное время и усилия направить на решение конкретных задач.

C++. Сборник рецептов - читать онлайн бесплатно полную версию (весь текст целиком)

C++. Сборник рецептов - читать книгу онлайн бесплатно, автор Д. Стефенс
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Несмотря на мою привычку тщательно подходить к кодированию программ, я сделал глупую ошибку и написал +=вместо +. В результате при вызове concatUnsafeбудут модифицированы аргументы outи s1, что может оказаться сюрпризом для пользователя, который едва ли рассчитывает на модификацию одной из исходных строк.

Спасти может const. Создайте новую функцию concatSafe, объявите переменные константными, как показано в примере 15.3, и функция не будет откомпилирована.

void concatSafe(const std::string& s1,

const std::string& s2, std::string& out) {

out = s1 += s2; // Теперь вы получите ошибку компиляции

}

concatSafегарантирует неизменяемость значений в s1и s2. Эта функция делает еще кое-что: она позволяет пользователю передавать константные аргументы. Например, программный код, выполняющий конкатенацию строк, мог бы выглядеть следующим образом.

void myFunc(const std::string& s) { // Обратите внимание, что s является

// константной переменной

std::string dest;

std::string tmp = "foo";

concatUnsafe(s, tmp, dest); // Ошибка: s - константная переменная

// Выполнить какие-то действия с dest...

}

В данном случае функция myFuncне будет откомпилирована, потому что concatUnsafeне обеспечивает const'антность myFunc. myFuncгарантирует внешнему миру, что она не будет модифицировать содержимое s, т.е. все действия с sвнутри тела myFuncне должны нарушать это обещание. Конечно, вы можете обойти это ограничение, используя оператор const_castи тем самым освобождаясь от константности, но такой подход ненадежен, и его следует избегать. В этой ситуации concatSafeбудет компилироваться и выполняться нормально.

Указатели вносят темные штрихи в розовую картину const. Когда вы объявляете переменную-указатель как параметр, вы имеет дело с двумя объектами: самим адресом и то, на что ссылается этот адрес. C++ позволяет использовать constдля ограничения действий по отношению к обоим объектам. Рассмотрим еще одну функцию конкатенации, которая использует указатели.

void concatUnsafePtr(std::string* ps1,

std::string* ps2, std::string* pout) {

*pout = *ps1 + *ps2;

}

Здесь такая же проблема, как в примере с concatUnsafe, описанном ранее. Добавьте constдля гарантии невозможности обновления исходных строк.

void concatSaferPtr(const std::string* ps1,

const std::string* ps2, std::string* pout) {

*pout = *ps1 + *ps2;

}

Отлично, теперь вы не можете изменить *ps1и *ps2. Но вы по-прежнему можете изменить ps1и ps2, или, другими словами, используя их, вы можете сослаться на какую-нибудь другую строку, изменяя значение указателя, но не значение, на которое он ссылается. Ничто не может помешать вам, например, сделать следующее.

void concatSaferPtr(const std:string* ps1,

const std::string* ps2, std::string* pout) {

ps1 = pout; // Ух!

*pout = *ps1 + *ps2;

}

Предотвратить подобные ошибки можно с помощью еще одного const.

void concatSafestPtr(const std::string* const ps1,

const std::string* const ps2, std::string* pout) {

*pout = *ps1 + *ps2;

}

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

См. также

Рецепт 15.4.

15.4. Обеспечение невозможности модификации своих объектов в функции-члене

Проблема

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

Решение

Поместите ключевое слово constсправа от имени функции-члена при ее объявлении в классе и при ее определении. Пример 15.4 показывает, как это можно сделать

Пример 15.4. Объявление функции-члена константной

#include

#include

class RecordSet {

public:

bool getFieldVal(int i, std::string& s) const;

// ...

};

bool RecordSet::getFieldVal(int i, std::string& s) const {

// Здесь нельзя модифицировать никакие неизменяемые

// данные-члены (см. обсуждение)

}

void displayRecords(const RecordSet& rs) {

// Здесь вы можете вызывать только константные функции-члены

// для rs

}

Обсуждение

Добавление концевого constв объявление члена и в его определение заставляет компилятор более внимательно отнестись к тому, что делается с объектом внутри тела члена. Константным функциям-членам не разрешается выполнять неконстантные операции с данными-членами. Если такие операции присутствуют, компиляция завершится неудачно. Например, если бы в RecordSet::getFieldValя обновил счетчик-член, эта функция не была бы откомпилирована (в предположении, что getFieldCount_является переменной-членом класса RecordSet).

bool RecordSet::getFieldVal(int i, std::string& s) const {

++getFieldCount_; // Ошибка: константная функция-член не может

// модифицировать переменную-член

// ...

}

Это может также помочь обнаружить более тонкие ошибки, подобно тому, что делает constв роли квалификатора переменной (см. рецепт 15.3). Рассмотрим следующую глупую ошибку.

bool RecordSet::getFieldVal(int i, std::string& s) const {

fieldArray_[i] = s; // Ой, я не это имел в виду

// ...

}

Снова компилятор преждевременно завершит работу и выдаст сообщение об ошибке, потому что вы пытаетесь изменить переменную-член, а это не разрешается делать в константных функциях-членах. Ну, при одном исключении.

В классе RecordSet(в таком, как (схематичный) класс в примере 15.4) вам, вероятно, потребовалось бы перемещаться туда-сюда по набору записей, используя понятие «текущей» записи. Простой способ заключается в применении переменной-члена целого типа, содержащей номер текущей записи; ваши функции-члены, предназначенные для перемещения текущей записи вперед-назад, должны увеличивать или уменьшать это значение.

void RecordSet::gotoNextPecord() const {

if (curIndex_ >= 0 && curIndex_ < numRecords_-1)

++curIndex_;

}

void RecordSet::gotoPrevRecord() const {

if (curIndex_ > 0)

--curIndex_;

}

Очевидно, что это не сработает, если эти функции-члены являются константными. Обе обновляют данное-член. Однако без этого пользователи класса RecordSetне смогут перемещаться по объекту const RecordSet. Это исключение из правил работы с константными функциями-членами является вполне разумным, поэтому C++ имеет механизм его поддержки: ключевое слово mutable.

Для того чтобы curIndex_можно было обновлять в константной функции-члене, объявите ее с ключевым словом mutable в объявлении класса.

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать


Д. Стефенс читать все книги автора по порядку

Д. Стефенс - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки LibKing.




C++. Сборник рецептов отзывы


Отзывы читателей о книге C++. Сборник рецептов, автор: Д. Стефенс. Читайте комментарии и мнения людей о произведении.


Понравилась книга? Поделитесь впечатлениями - оставьте Ваш отзыв или расскажите друзьям

Напишите свой комментарий
x