Чтение онлайн

на главную - закладки

Жанры

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

Когсуэлл Джефф

Шрифт:

Спасти может

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 <iostream>

#include <string>

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). Рассмотрим следующую глупую ошибку.

Поделиться:
Популярные книги

Печать Пожирателя

Соломенный Илья
1. Пожиратель
Фантастика:
попаданцы
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Печать Пожирателя

Привет из Загса. Милый, ты не потерял кольцо?

Лисавчук Елена
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Привет из Загса. Милый, ты не потерял кольцо?

Мастер 2

Чащин Валерий
2. Мастер
Фантастика:
фэнтези
городское фэнтези
попаданцы
технофэнтези
4.50
рейтинг книги
Мастер 2

Нечто чудесное

Макнот Джудит
2. Романтическая серия
Любовные романы:
исторические любовные романы
9.43
рейтинг книги
Нечто чудесное

Клан

Русич Антон
2. Долгий путь домой
Фантастика:
боевая фантастика
космическая фантастика
5.60
рейтинг книги
Клан

Имя нам Легион. Том 3

Дорничев Дмитрий
3. Меж двух миров
Фантастика:
боевая фантастика
рпг
аниме
5.00
рейтинг книги
Имя нам Легион. Том 3

Запасная дочь

Зика Натаэль
Фантастика:
фэнтези
6.40
рейтинг книги
Запасная дочь

Убивать чтобы жить 7

Бор Жорж
7. УЧЖ
Фантастика:
героическая фантастика
космическая фантастика
рпг
5.00
рейтинг книги
Убивать чтобы жить 7

У врага за пазухой

Коваленко Марья Сергеевна
5. Оголенные чувства
Любовные романы:
остросюжетные любовные романы
эро литература
5.00
рейтинг книги
У врага за пазухой

Кодекс Охотника. Книга XXI

Винокуров Юрий
21. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга XXI

Генерал Скала и ученица

Суббота Светлана
2. Генерал Скала и Лидия
Любовные романы:
любовно-фантастические романы
6.30
рейтинг книги
Генерал Скала и ученица

Оцифрованный. Том 1

Дорничев Дмитрий
1. Линкор Михаил
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Оцифрованный. Том 1

Его маленькая большая женщина

Резник Юлия
Любовные романы:
современные любовные романы
эро литература
8.78
рейтинг книги
Его маленькая большая женщина

Хуррит

Рави Ивар
Фантастика:
героическая фантастика
попаданцы
альтернативная история
5.00
рейтинг книги
Хуррит