C++. Сборник рецептов - [203]
В отличие от данного члена с функцией-членом вы не можете сделать то же самое, потому что это бессмысленно. Рассмотрим указатель на функцию, имеющую такую же сигнатуру, как >MyClass::incr
(т.е. он возвращает >void
и не имеет аргументов).
>void (*pf)();
Теперь попытайтесь присвоить этому указателю адрес функции-члена.
>pf = &MyClass::incr; // He получится
>pf = &obj.incr; // И это не пройдет
Обе эти строки не будут откомпилированы, и на это имеются веские основания. Применение функции-члена имеет разумный смысл только в контексте объекта, поскольку, вероятнее всего, она должна ссылаться на переменные-члены. Вызов функции-члена без объекта означало бы невозможность в функции-члене использовать какие-либо члены объекта, а эта функция, по-видимому, как раз является функцией-членом, а не автономной функцией, потому что использует члены объекта.
Рецепт 15.1.
15.3. Обеспечение невозможности модификации аргумента в функции
Вы пишете функцию и требуется гарантировать, что ее аргументы не будут модифицированы при ее вызове.
Для предотвращения изменения аргументов вашей функцией объявите ее аргументы с ключевым словом >const
. Короткий пример 15.3 показывает, как это можно сделать.
Пример 15.3. Гарантия невозможности модификации аргументов
>#include
>#include
>void concat(const std::string& s1, // Аргументы объявлены как константное,
> const std::string& s2, // поэтому не могут быть изменены
> std::string& out) {
> out = s1 + s2;
>}
>int main() {
> std::string s1 = "Cabo ";
> std::string s2 = "Wabo";
> std::string s3;
> concat(s1, s2, s3);
> std::cout << "s1 = " << s1 << '\n';
> std::cout << "s2 = " << s2 << '\n';
> std::cout << "s3 = " << s3 << '\n';
>}
В примере 15.3 продемонстрировано прямое использование ключевого слова >const
. Существует две причины объявления параметров вашей функции с этим ключевым словом, когда вы не планируете их изменять. Во-первых, этим вы сообщаете о своих намерениях читателям вашего программного кода. Объявляя параметр как >const
, вы фактически говорите, что он является входным параметром. Это позволяет пользователям вашей функции писать программный код в расчете на то, что эти значения не будут изменены. Во-вторых, это позволяет компилятору запретить любые модифицирующие операции на тот случай, если вы случайно их используете. Рассмотрим небезопасную версию >concat
из примера 15 3.
>void concatUnsafe(std::string& s1,
> std::string& s2 std::string& out) {
> out = s1 += s2; // Ну вот, записано значение в s1
>}
Несмотря на мою привычку тщательно подходить к кодированию программ, я сделал глупую ошибку и написал >+=
вместо >+
. В результате при вызове >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
, или, другими словами, используя их, вы можете сослаться на какую-нибудь другую строку, изменяя значение указателя, но не значение, на которое он ссылается. Ничто не может помешать вам, например, сделать следующее.

Java Enterprise Edition (Java EE) остается одной из ведущих технологий и платформ на основе Java. Данная книга представляет собой логичное пошаговое руководство, в котором подробно описаны многие спецификации и эталонные реализации Java EE 7. Работа с ними продемонстрирована на практических примерах. В этом фундаментальном издании также используется новейшая версия инструмента GlassFish, предназначенного для развертывания и администрирования примеров кода. Книга написана ведущим специалистом по обработке запросов на спецификацию Java EE, членом наблюдательного совета организации Java Community Process (JCP)

Что такое ГЕЙМДИЗАЙН? Это не код, графика или звук. Это не создание персонажей или раскрашивание игрового поля. Геймдизайн – это симулятор мечты, набор правил, благодаря которым игра оживает. Как создать игру, которую полюбят, от которой не смогут оторваться? Знаменитый геймдизайнер Тайнан Сильвестр на примере кейсов из самых популярных игр рассказывает как объединить эмоции и впечатления, игровую механику и мотивацию игроков. Познакомитесь с принципами дизайна, которыми пользуются ведущие студии мира! Создайте игровую механику, вызывающую эмоции и обеспечивающую разнообразие.

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

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

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

Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.