逐个成员赋值和初始化

用于默认赋值和初始化的方法分别为“按成员赋值”和“按成员初始化”。 按成员赋值包括一次将一个对象复制到其他对象,就像分别分配每个成员一样。 按成员初始化包括一次将一个对象复制到其他对象,就像分别初始化每个成员一样。 两者之间的主要区别在于按成员赋值调用了每个成员的赋值运算符 (operator=),而按成员初始化调用了每个成员的复制构造函数。

按成员赋值仅由按以下形式声明的赋值运算符执行:

type**&** type :: operator=( [const | volatile] type**&** )

如果满足以下任一条件,则无法为按成员赋值生成默认赋值运算符:

  • 成员类具有 const 成员。

  • 成员类具有引用成员。

  • 成员类或其基类具有私有赋值运算符 (operator=)。

  • 基类或成员类没有赋值运算符 (operator=)。

如果类或它的某个基类具有私有复制构造函数或者满足以下任一条件,则无法为按成员初始化生成默认复制构造函数:

  • 成员类具有 const 成员。

  • 成员类具有引用成员。

  • 成员类或其基类具有私有复制构造函数。

  • 基类或成员类没有复制构造函数。

总是会声明给定类的默认赋值运算符和复制构造函数,但不会定义它们,除非满足以下两个条件:

  • 该类没有为此副本提供用户定义的函数。

  • 程序要求函数存在。 如果遇到需要按成员复制的赋值或初始化,或者采用了类的 operator= 函数的地址,则此要求存在。

如果这些条件均未满足,则生成默认赋值运算符的代码和复制构造函数不需要编译器(此类代码的清除是 Microsoft C++ 编译器执行的优化)。 具体而言,如果该类声明了一个用户定义的 operator=,而后者采用了“对 class-name 的引用”类型的参数,则不会生成默认赋值运算符。 如果类声明了一个复制构造函数,则不会生成默认复制构造函数。

因此,对于给定类 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 的引用)的参数,checking 的 Account 子对象将复制到 account;不会复制 fOverdraftProtect。

请参见

参考

复制类对象