Назначение и инициализация по членам
Методы назначения и инициализации по умолчанию называются почленным назначением и почленной инициализацией соответственно. Почленное назначение состоит из копирования одного объекта в другой, по одному члену за раз, как если бы каждый член назначался по отдельности. Почленная инициализация состоит из копирования одного объекта в другой, по одному члену за раз, как если бы каждый член инициализировался по отдельности. Основное различие между ними состоит в том, что при почленном назначении вызывается оператор присваивания каждого члена (operator=), а при почленной инициализации вызывается конструктор копии каждого члена.
Почленное назначение выполняется только с помощью оператора присваивания, объявленного в следующей форме.
type**&** type :: operator=( [const | volatile] type**&** )
Операторы присваивания по умолчанию для почленного назначения невозможно создать, если выполняется любое из следующих условий.
Класс члена имеет члены const.
Класс члена имеет ссылочные члены.
Класс члена или его базовый класс имеет закрытый оператор присваивания (operator=).
Базовый класс или класс члена не имеет оператор присваивания (operator=).
Конструкторы копии по умолчанию для почленной инициализации невозможно создать, если класс или один из его базовых классов имеет закрытый конструктор копии или если выполняется любое из следующих условий.
Класс члена имеет члены const.
Класс члена имеет ссылочные члены.
Класс члена или его базовый класс имеет закрытый конструктор копии.
Базовый класс или класс члена не имеет конструктор копии.
Операторы присваивания и конструкторы копии по умолчанию для данного класса объявляются всегда, но определяются, только если выполняются оба приведенных ниже условия.
Класс не предоставляет определяемую пользователем функцию для данной копии.
Для программы требуется наличие данной функции. Это требование применимо в случае назначения или инициализации, для которых требуется почленное копирование, или при использовании адреса функции operator= класса.
Если оба эти условия не выполняются, не требуется, чтобы компилятор создавал код для функций оператора присваивания и конструктора копии по умолчанию (исключением из такого кода является оптимизация, выполненная компилятором Microsoft C++). В частности, если класс объявляет определенную пользователем функцию operator=, которая принимает аргумент типа "ссылка на имя_класса", оператор присваивания по умолчанию не создается. Если класс объявляет конструктор копии, конструктор копии по умолчанию не создается.
Следовательно, для данного класса A всегда присутствуют следующие объявления.
// Implicit declarations of copy constructor
// and assignment operator.
A::A( const A& );
A& A::operator=( const A& );
Определения предоставляются только при необходимости (в соответствии с указанными выше условиями). Функции конструктора копии, представленные в предыдущем примере, считаются открытыми функциями-членами класса.
Операторы присваивания по умолчанию позволяют назначать объекты данного класса объектам открытого типа базового класса. Рассмотрим следующий код.
Пример
// spec1_memberwise_assignment_and_initialization.cpp
#include<stdio.h>
class Account
{
protected:
int _balance;
public:
int getBalance()
{
return _balance;
}
};
class Checking : public Account
{
private:
int _fOverdraftProtect;
public:
Checking(int balance, int fOverdraftProtect)
{
_balance = balance;
_fOverdraftProtect = fOverdraftProtect;
}
};
int main()
{
Account account;
Checking checking(1000, 1);
account = checking;
printf_s("Account balance = %d\n", account.getBalance());
}
Комментарий
В предыдущем примере выбран оператор присваивания Account::operator=. Поскольку функция operator= по умолчанию принимает аргумент типа Account& (ссылка на Account), вложенный объект Account checking копируется в account; fOverdraftProtect не копируется.