Assign values to all data members in operator =

Source: Internet
Author: User
Clause 45 states that if no value assignment operator is set, the compiler will generate one for you. Clause 11 explains why you often dislike the compiler for you.
Therefore, you may wonder if there is a perfect way for the compiler to generate a default value assignment operator.
Write a dislike part. This is impossible! To control a part of the assignment process, you must be responsible for all the tasks in the assignment process.
In actual programming, this means that each data member of the object must be assigned a value when the value assignment operator is written:

Code

Template < Class T >   // Template of the class associated with the name and pointer
Class Namedptr { // (From clause 12)
Public :
Namedptr ( Const   String & Initname, T * Initptr );
Namedptr &   Operator = ( Const Namedptr & RHS );
Private :
String Name;
T * PTR;
};
Template < Class T >
Namedptr < T > & Namedptr < T > :: Operator = ( Const Namedptr < T > & RHS)
{
If ( This   =   & RHS)
Return   * This ; // See article 17
// Assign to all data members
Name = RHS. Name; // Assign name values
* PTR =   * RHS. PTR; // For PTR, the value assigned is the value indicated by the pointer,
// Not the pointer itself
Return   * This ; // See article 15
}

 

It is easy to remember the above principles when writing this class, but it is also important to remember to update the value assignment operator letter when new data members are added to the class.
Number. For example, if you want to upgrade the namedptr template to include a time mark when the name changes, you need to add a new data member and update the constructor.
Number and value assignment operator. However, in reality, it is easy to forget to update the specific functions of the class and add new member functions.
When inheritance is involved, the situation will be more interesting, because the assignment operator of the derived class must also handle the assignment of its base class members! Take a look at the following:

Code

Class   Base {
Public :
Base ( Int Initialvalue =   0 ): X (initialvalue ){}
Private :
Int X;
};
Class Derived: Public   Base {
Public :
Derived ( Int Initialvalue)
: Base (Initialvalue), y (initialvalue ){}
Derived &   Operator = ( Const Derived & RHS );
Private :
Int Y;
};

 

Logically, the value assignment operator of derived should be like this:

// Erroneous assignment operator
Derived & Derived :: Operator = ( Const Derived & RHS)
{
If ( This   =   & RHS) Return   * This ; // See article 17
Y = RHS. Y; // Only
// Data member assignment
Return   * This ; // See article 15
}

 

Unfortunately, it is incorrect because the data member X of the base part of the derived object is not affected in the value assignment operator. For example, consider the followingCodeSection:

Void Assignmenttester ()
{
Derived D1 ( 0 ); // D1.x = 0, d1.y = 0
Derived D2 ( 1 ); // D2.x = 1, d2.y = 1
D1 = D2; // D1.x = 0, d1.y = 1!
}

 

Note that the base part of D1 is not changed by the value assignment operation.
The most obvious solution to this problem is to assign a value to X in derived: Operator =. However, this is not legal because X is a private member of the base. Therefore, you must
The value assignment operator explicitly assigns values to the base part of derived.
That is to say:

// Correct value assignment operator
Derived & Derived :: Operator = ( Const Derived & RHS)
{
If ( This   =   & RHS) Return   * This ;
Base :: Operator = (RHs ); // Call this-> base: Operator =
Y = RHS. Y;
Return   * This ;
}

 

Here, we only explicitly call base: Operator =. This call is the same as calling another member function in a member function in general, with * this as its
Implicit left value. Base: Operator = will execute all the work it should do for the base part of * This-just as you expected.
However, if the base class assignment operator is generated by the compiler, Some compilers reject this call to the base class assignment operator (see article 45 ). To adapt to this
The compiler must implement derived: Operator =:

Derived & Derived :: Operator = ( Const Derived & RHS)
{
If ( This   =   & RHS) Return   * This ;
Static_cast < Base &> ( * This ) = RHS; // For the Base Section of * This
// Call operator =
Y = RHS. Y;
Return   * This ;
}

 

This weird code forcibly converts * this to a base reference and then assigns a value to the conversion result. Here, only the base part of the derived object is assigned a value. Note that
It is important to convert the reference of the base object instead of the base object itself. If you forcibly convert * this to a base object, you must call the base copy function.
The new object created by the constructor (see the M19 clause) becomes the goal of value assignment, and * This remains unchanged. This is not the expected result.
No matter which method is used, after assigning a value to the base part of the derived object, it is followed by the value of the derived itself, that is, assigning a value to all data members of the derived object.
Another common issue related to inheritance is when copying constructors of derived classes. Let's take a look at the following constructor. Its code is discussed above.
The theory is similar:
The theory is similar:

Code

Class   Base {
Public :
Base ( Int Initialvalue =   0 ): X (initialvalue ){}
Base ( Const   Base & RHS): X (RHS. X ){}
Private :
Int X;
};
Class Derived: Public   Base {
Public :
Derived ( Int Initialvalue)
: Base (Initialvalue), y (initialvalue ){}
Derived ( Const Derived & RHS) // Incorrect copy
: Y (RHS. Y ){} // Constructor
Private :
Int Y;
};

 

The derived class shows a bug that occurs in all c ++ environments: When a copy of the derived is created, the basic class is not copied. Of course, this derived
The base part of the object is still created, but it is created using the default base constructor. The member X is initialized to 0 (the default parameter value of the default constructor ).
The X value of the Copied object is not taken into account!
To avoid this problem, the derived copy constructor must call the base copy constructor instead of the base default constructor. This is easy to do,
You only need to specify an initialization value for base in the member initialization list of the copy constructor of derived:

Class Derived: Public   Base {
Public :
Derived ( Const Derived & RHS ): Base (RHs), y (RHS. Y ){}
...
};

 

Now, when an existing object of the same type is used to copy and create a derived object, its base part will also be copied.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.