Private-Bookers
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

}

  • Читать дальше
  • 1
  • ...
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270

Private-Bookers - русскоязычная библиотека для чтения онлайн. Здесь удобно открывать книги с телефона и ПК, возвращаться к сохраненной странице и держать любимые произведения под рукой. Материалы добавляются пользователями; если считаете, что ваши права нарушены, воспользуйтесь формой обратной связи.

Полезные ссылки

  • Моя полка