|
| |||
|
|
Вопросы по С++ и не только. Не все вопросы касаются именно языка C++. Как например, 11. Это, скорее, способ мышления.
Ключевое слово explicit используется при объявлении конструктора класса, во избежании нежелательного неявного преобразования типов. Реализуя параметризованный (скажем, int) конструктор для некоторого класса (скажем, A), мы тем самым даем возможность этому преобразованию A a = 5;. Ясно, что выполнится как раз параметризованный конструктор, при условии отсутствия explicit и реализации оператора присваивания. Указание спецификатора mutable у некоторого члена класса переопределяет свойство постоянства у этого члена. Проще говоря, такие члены могут быть модифицированы const-методами класса. Вообще, есть подозрение, что за mutable стоит длинная история, а также зачастую он вызывает множество недоумений. Однозначно нет. В static функции не передается указатель this. В const - передается, да еще и константный. Преобразование типов в C++. Есть мнение, что использование этих ключевых слов очень редко бывает обоснованным. Снятие квалификаторов const, volatile с переменной. Ошибка приведения - ошибка компиляции. Приведение указателей либо ссылок на полиморфные классы друг к другу. Полиморфизм означает в данном случае наличие хоть одной виртуальной функции и он критичен для dynamic_cast: ошибка компиляции в противном случае. Ошибка выполнения сигнализируется возвращенным NULL в случае указателей и сообщением bad_cast в случае ссылок. Приведение одного типа к другому. Используются встроенные правила в случае встроенных типов, свои правила в случае своих. Если речь идет об указателях, то либо один из них обязан быть void *, либо оба должны указывать на объекты классов из одной иерархии. Ошибка приведения - ошибка компиляции и undefined behavior в случае ошибки приведения указателей на объекты классов из одной иерархии. Вообще инстанцирование есть создание экземпляра класса. Инстанцирование шаблонов судя по всему есть полиморфное инстанцирование. Пример: vector<int> a; Остается неясным обязательна ли при инстанцировании аллокация. Синтаксически это определение еще одного шаблона, отличающегося от общего лишь подстановкой фактических типов или значений. Специализированный шаблон может иметь собственные методы и члены, он не связан с общим. Может использоваться, например, для оптимизации реализации некоторого случая для особого типа. Частичная специализация шаблона неявно конкретизируется при использовании в программе, а именно: если для шаблона класса объявлены частичные специализации, компилятор выбирает то определение, которое является наиболее специализированным для заданных аргументов. В C++ нет такой возможности. Ее отсутствие часто аргументируют примером, в котором показана ошибочность интуиции разработчика. Виртуальный деструктор необходим для корректного удаления экземпляра класса через указатель на экземпляр базового класса. Отличиями от обычной виртуальной функции являются: всегда имеет тело, при наследовании не перегружается, а расширяется в том смысле, что при вызове сначала выполняются деструкторы производных классов, а затем базового. Таким образом классы-наследники класса с одной виртуальной функцией - деструктором полиморфными не являются. Используется для придания абстрактности классу, запрета инстанцирования объекта данного класса. Миф о том, что не может иметь тела - миф, тело может быть, хоть это и не соответствует нынешнему стандарту. Отличается от чисто виртуальных функций тем, что производные классы не обязаны иметь определения деструктора. Объект не создается, деструктор в дальнейшем не вызывается, отсюда возможная проблема - утечки памяти. Полиморфизм - взаимозаменяемость объектов с одинаковым интерфейсом. "Один интерфейс, много методов". Перегрузка операторов и функций, шаблоны, параметры по умолчанию - это примеры полиморфизма, относящегося ко времени компиляции. Полиморфизм периода выполнения реализуется использованием виртуальных функций. Надо заметить, что полиморфизм времени выполнения неразрывно связан с использование производных классов так как без них использование виртуальности не имеет смысла. Часто случается, что класс-родитель содержит меньше информации, чем класс-потомок. Присваивание объекту класса-родителя объект класса-потомка, либо передачу в функцию, принимающую объект класса-родителя, объекта класса-потомка и называют срезкой. Процесс разрешения перегрузки разделяют на три этапа: Имеется информация как минимум о двух случаях обоснованности определения конструкторов в private: Run-Time Type Identification. Динамическая идентификация типов. В языке С++ возникают ситуации, в которых тип объекта неизвестен во время компиляции, так как его природа сможет быть выяснена только в период выполнения. Полиморфизм влечет за собой такие ситуации. Инструментами RTTI в C++ являются операторы dynamic_cast и typeid. Последний используется для получения типа объекта во время выполнения программы. Аналог динамического assert для времени компиляции. Примеры реализации: Liskov substitution principle. Принцип подстановки Барбары Лисков. Формулируется следующим образом: "Пусть q(x) является свойством верным относительно объектов x некоторого типа T. Тогда q(y) также должно быть верным для объектов y типа S, где S является подтипом типа T." Проще говоря, классы наследники обязаны обеспечивать ожидаемое обуславливаемое предком внешнее поведение. Формулировка: "Программы и сущности (классы, модули, функции) должны быть открыты для расширения и закрыты для изменения" По стандарту семантических и синтаксических различий нет. Тут надо заметить, во избежании путаницы, что речь идет об отличиях указанных ключевых слов в контексте разговора о параметрах шаблонов. Ясно, что например при определении класса нужно писать class, а не typename. |
|||||||||||||||