Читать «Эффективный и современный С++. 42 рекомендации по использованию С++11 и С++14» онлайн - страница 57

Скотт Мейерс

Чтобы сделать классы потоков некопируемыми, basic_ios в С++98 объявлен следующим образом (включая комментарии):

template <class charT, class traits = char_traits<charT> >

class basic_ios : public ios_base {

public:

 …

private:

 basic_ios(const basic_ios&);            // Не определен

 basic_ios& operator=(const basic_ios&); // Не определен

};

Объявление этих функций как private предотвращает их вызов клиентами. Умышленное отсутствие их определений означает, что если код, все еще имеющий к ним доступ (т.e. функции-члены или друзья класса), ими воспользуется, то компоновка (редактирование связей) будет неудачной из-за отсутствия определений функций.

В С++11 имеется лучший способ достичь по сути того же самого: воспользоваться конструкцией “= delete”: чтобы пометить копирующий конструктор и копирующее присваивание как удаленные функции. Вот та же часть basic_ios в С++11:

template <class charT, class traits = char_traits<charT> >

class basic_ios : public ios_base {

public:

 basic_ios(const basic_ios& ) = delete;

 basic_ios& operator=(const basic_ios&) = delete;

};

Отличие удаления этих функций от их объявления как private может показаться больше вопросом вкуса, чем чем-то иным, но на самом деле в это заложено больше, чем вы думаете. Удаленные функции не могут использоваться никоим образом, так что даже код функции- члена или функций, объявленных как friend, не будет компилироваться, если попытается копировать объекты basic_ios. Это существенное улучшение по сравнению с поведением С++98, где такое некорректное применение функций не диагностируется до компоновки.

По соглашению удаленные функции объявляются как public, а не private. Тому есть причина. Когда код клиента пытается использовать функцию-член, С++ проверяет доступность до проверки состояния удаленности. Когда клиентский код пытается использовать функцию, объявленную как private, некоторые компиляторы жалуются на то, что это закрытая функция, несмотря на то что доступность функции никак не влияет на возможность ее использования. Стоит принять это во внимание при пересмотре старого кода и замене не определенных функций-членов, объявленных как private, удаленными, поскольку объявление удаленных функций как public в общем случае приводит к более корректным сообщениям об ошибках.

Важным преимуществом удаленных функций является то, что удаленной может быть любая функция, в то время как быть private могут только функции-члены. Предположим, например, что у нас есть функция, не являющаяся членом, которая принимает целочисленное значение и сообщает, является ли оно “счастливым числом”: