Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ | страница 11
>void doSomething(B bObject); // функция принимает объект типа B
>B bObj1; // объект типа B
>doSomething(bObj1); // нормально, B передается doSomething
>B bObj(28); // нормально, создает B из целого 28
>// (параметр bool по умолчанию true)
>doSomething(28); // ошибка! doSomething принимает B,
>// а не int, и не существует неявного
>// преобразования из int в B
>doSomething(B(28)); // нормально, используется конструктор
>// B для явного преобразования (приведения)
>// int в B (см. в правиле 27 информацию
>// о приведении типов)
Конструкторы, объявленные как explicit, обычно более предпочтительны, потому что предотвращают выполнение компиляторами неявных преобразований типа (часто нежелательных). Если нет основательной причины для использования конструкторов в неявных преобразованиях типов, я всегда объявляю их explicit. Советую и вам придерживаться того же принципа.
Обратите внимание, что в предшествующем примере приведение выделено. Я и дальше буду использовать такое выделение, чтобы подчеркнуть важность излагаемого материала. (Также я выделяю номера глав, но это только потому, что мне кажется, это выглядит симпатично.)
Конструктор копирования (copy constructor) используется для инициализации объекта значением другого объекта того же самого типа, а копирующий оператор присваивания (copy assignment operator) применяется для копирования значения одного объекта в другой – того же типа:
>class Widget {
>public:
>Widget(); // конструктор по умолчанию
>Widget(const Widget& rhs); // конструктор копирования
>Widget& operator=(const Widget& rhs); // копирующий оператор присваивания
>...
>};
>Widget w1; // вызов конструктора по умолчанию
>Widget w2(w1); // вызов конструктора копирования
>w1 = w2; // вызов оператора присваивания
>// копированием
Будьте внимательны, когда видите конструкцию, похожую на присваивание, потому что синтаксис «=» также может быть использован для вызова конструктора копирования:
>Widget w3 = w2; // вызов конструктора копирования!
К счастью, конструктор копирования легко отличить от присваивания. Если новый объект определяется (как w3 в последнем предложении), то должен вызываться конструктор, это не может быть присваивание. Если же никакого нового объекта не создается (как в «w1=w2»), то конструктор не применяется и это – присваивание.
Конструктор копирования – особенно важная функция, потому что она определяет, как объект передается по значению. Например, рассмотрим следующий фрагмент:
>bool hasAcceptableQuality(Widget w);