|
Программирование >> Обобщенные обратные вызовы
рекомендация №3: виртуальную функцию можно делать защищенной только в том случае, когда производному классу требуется вызов реализации виртуальной функции в базовом классе. Единственное исключение делается для деструктора: рекомендация №4: деструктор базового класса должен быть либо открытым и виртуальным, либо защищенным и невиртуальным. Правда, сама стандартная библиотека не всегда следует всем этим рекомендациям. Частично это отражение процесса накопления знаний сообществом программистов С++. Задача 19. Не можешь - научим, не хочешь - заставим! (или как заставить потомков вести себя прилично) Сложность: 5 Оказывается, иногда вы можете уберечь программистов производных классов от некоторых простых ошибок. Эта задача - о безопасном дизайне базовых классов, который не позволяет разработчикам производных классов пойти неверным путем. Вопрос для новичка 1. В каком случае происходит неявное объявление и определение перечисленных ниже функций? С какой семантикой? Будьте точны и опишите условия, при которых их неявно определенные версии делают программы некорректными: а) конструктор по умолчанию; б) копирующий конструктор; в) копирующий оператор присваивания; г) деструктор. 2. Какие функции неявно объявлены и созданы компилятором в следующем классе х? С какими сигнатурами? class X { auto ptr<int> i ; Вопрос для профессионала 3. Пусгь у вас есть базовый класс, который требует, чтобы все производные классы не использовали ни одной неявно объявленной и созданной компилятором функции. Например: class Count { publтс: Этим комментарием автор класса Count документирует, что производные классы должны наследоваться виртуально, и что их конструкторы должны вызывать конструктор класса Count специального назначения. Count( /* Специальные параметры */ ); Count& operator=( const Count& ); обычный virtual ~Count(); Обычный К сожалению, программистам, как и всем остальным людям, свойственно ошибаться, так что иногда они будут забывать, что они обязаны явно написать две функции. class Badoerived : private vi rtual Count { int i ; Конструктор no умолчанию: должен вызывать специальный конструктор, но делает ли он это? копирующий конструктор: должен вызывать специальный конструктор, но делает ли он это? копирующее присваивание: ок? деструктор: ок? Имеется ли способ в контексте этого примера, при помощи которого автор класса count мог бы заставить автора производного класса программировать в соответствии с указанными правилами - т.е. чтобы сообщение об ошибке выдавалось во время компиляции (предпочтительно) или хотя бы во время выполнения программы, если автор производного класса нарушил указанное в комментарии к классу Count требование? Вопрос в общем виде: имеется ли способ, при помощи которого автор базового класса может заставить автора производного класса явным образом написать каждую из четырех перечисленных выше базовых операций? Если да, то как? Если нет, то почему? Решение Неявно генерируемые функции В С++ компилятор может неявно генерировать четыре функции-члена класса: конструктор по умолчанию, копирующий конструктор, оператор копирующего присваивания и деструктор. Причина этого заключается в сочетании удобства и обратной совместимости с С. Вспомним, что сфуктуры в стиле С struct - это просто классы, содержащие только открытые члены-данные; в частности, они не должен иметь (явно определенных) функций-членов, и все же должен существовать способ создавать, копировать и уничтожать их. Для этого С++ автоматически генерирует соответствующие функции (или некоторое их подмножество) для выполнения указанных действий, если вы не определили их самостоятельно. В задаче спрашивается о том, что именно означает слово соответствующие . 1. В каком случае происходит неявное объявление и определение перечисленных ниже функций? С какой семантикой? Будьте точны и опишите условия, при которых их неявно определенные версии делают программы некорректными. Говоря кратко, неявно объявленная функция становится неявно определенной только при попытке се использовать. Например, неявно объявленный конструктор по умолчанию неявно создается компилятором только тогда, когда вы пытаетесь создать объект без указания параметров конструктора. Почему следует различать случаи неявного объявления и неявного определения функции? Потому что вполне реальна ситуация, когда функция никогда не вызывается, и если это так, то программа остается корректной даже если неявное определение функции некорректно. Для удобства в этой задаче, если явно не оговорено иное, член означает нестатический член-данные класса . Кроме того, я буду говорить неявно сгенерированные , подразумевая неявно объявленные и определенные . Спецификации исключений неявно определенных функций Во всех четырех случаях неявного объявления функций компилятор делает их спецификации исключений достаточно свободными, допускающими генерацию любых исключений неявно определенными функциями. Например: пример 19-1(а) class с ... { ...
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |