Стандарты программирования на С++. 101 правило и рекомендация | страница 78
> // данного кода)
> }
>};
>Calc с;
>с.Twice("Hello"); // Б: ошибка, функция 3
> // недоступна (могла бы использоваться
> // функция 2, но она не рассматривается, так
> // как у функции 3 лучшее соответствие
> // аргументу)
В строке А обходной путь состоит в том, чтобы явно квалифицировать вызов как >::Twice(21)
для того, чтобы заставить поиск имен выбрать глобальную функцию. В строке Б обходной путь состоит в добавлении явного преобразования типа >с.Twiсе(string("Hellо"))
для того, чтобы заставить разрешение перегрузки выбрать соответствующую функцию. Некоторые из таких проблем, связанных с вызовами, можно решить и без применения идиомы Pimpl, например, никогда не используя закрытые перегрузки функций-членов, но не для всех проблем, разрешимых при помощи идиомы Pimpl, можно найти такие обходные пути.
Третье следствие влияет на обработку ошибок и безопасность. Рассмотрим пример >Widget
Тома Каргилла (Tom Cargill):
>class Widget { // ...
>public:
> Widget& operator=(const Widget&);
>private:
> T1 t1_;
> T2 t2_;
>};
Коротко говоря, мы не можем написать оператор >operator=
, который обеспечивает строгую гарантию (или хотя бы базовую гарантию), если операции >T1
или >T2
могут давать необратимые сбои (см. рекомендацию 71). Хорошие новости, однако, состоят в том, что приведенная далее простая трансформация всегда обеспечивает, как минимум, базовую гарантию для безопасного присваивания, и как правило — строгую гарантию, если необходимые операции >T1
и >T2
(а именно — конструкторы и деструкторы) не имеют побочных эффектов. Для этого следует хранить объекты не по значению, а посредством указателей, предпочтительно спрятанными за единственным указателем на реализацию:
>class Widget { // ...
>public:
> Widget& operator=(const Widget&);
>private:
> struct Impl;
> shared_ptr
>};
>Widget& Widget::operator=( const Widget& ) {
> shared_ptr
> // изменяем temp->t1_ и temp->t2_; если какая-то из
> // операций дает сбой, генерируем исключение, в
> // противном случае - принимаем внесенные изменения:
> pimpl_ = temp;
> return *this;
>}
В то время как вы получаете все преимущества дополнительного уровня косвенности, проблема состоит только в увеличении сложности кода (см. рекомендации 6 и 8).
[Coplien92] §5.5 • [Dewhurst03] §8 • [Lakos96] §6.4.2 • [Meyers97] §34 • [Murray93] §3.3 • [Stroustrup94] §2.10, §24.4.2 • [Sutter00] §23, §26-30 • [Sutter02] §18, §22 • [Sutter04] §16-17
44. Предпочитайте функции, которые не являются ни членами, ни друзьями