Поделиться через


Назначение и инициализация по членам

Методы назначения и инициализации по умолчанию называются почленным назначением и почленной инициализацией соответственно. Почленное назначение состоит из копирования одного объекта в другой, по одному члену за раз, как если бы каждый член назначался по отдельности. Почленная инициализация состоит из копирования одного объекта в другой, по одному члену за раз, как если бы каждый член инициализировался по отдельности. Основное различие между ними состоит в том, что при почленном назначении вызывается оператор присваивания каждого члена (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 не копируется.

См. также

Ссылки

Копирование объектов классов