Стандарты программирования на С++. 101 правило и рекомендация | страница 70
См. также рекомендацию 54.
NVI не применим к деструкторам в связи со специальным порядком их выполнения (см. рекомендацию 50).
NVI непосредственно не поддерживает ковариантные возвращаемые типы. Если вам требуется ковариантность, видимая вызывающему коду без использования dynamic_cast (см. также рекомендацию 93), проще сделать виртуальную функцию открытой.
[Allison98] §10 • [Dewhurst03] §72 • [Gamma95] • [Keffer95 pp. 6-7] • [Koenig97] §11 • [Sutter00] §19, §23 • [Sutter04] §18
40. Избегайте возможностей неявного преобразования типов
Не все изменения прогрессивны: неявные преобразования зачастую приносят больше вреда, чем пользы. Дважды подумайте перед тем, как предоставить возможность неявного преобразования к типу и из типа, который вы определяете, и предпочитайте полагаться на явные преобразования (используйте конструкторы, объявленные как >explicit
, и именованные функции преобразования типов).
Неявные преобразования типов имеют две основные проблемы.
• Они могут проявиться в самых неожиданных местах.
• Они не всегда хорошо согласуются с остальными частями языка программирования.
Неявно преобразующие конструкторы (конструкторы, которые могут быть вызваны с одним аргументом и не объявлены как >explicit
) плохо взаимодействуют с перегрузкой и приводят к созданию невидимых временных объектов. Преобразования типов, определенные как функции-члены вида >operator T
(где >T
— тип), ничуть не лучше — они плохо взаимодействуют с неявными конструкторами и позволяют без ошибок скомпилировать разнообразные бессмысленные фрагменты кода (примеров чего несть числа — см. приведенные в конце рекомендации ссылки; мы приведем здесь только пару из них).
В С++ последовательность преобразований типов может включать не более одного пользовательского преобразования. Однако когда в эту последовательность добавляются встроенные преобразования, ситуация может оказаться предельно запутанной. Решение здесь простое и состоит в следующем.
• По умолчанию используйте explicit в конструкторах с одним аргументом (см. рекомендацию 54):
>class Widget { // ...
> explicit Widget(unsigned int widgetizationFactor);
> explicit Widget(const char* name, const Widget* other = 0);
>};
• Используйте для преобразований типов именованные функции, а не соответствующие операторы:
>class String { // ...
> const char* as_char_pointer() const; // в традициях c_str
>};
См. также обсуждение копирующих конструкторов, объявленных как