简体   繁体   中英

Default assignment operator has access to private members of base class

My problem is very easily explained by this example :

http://pastebin.com/VDBE3miY

class Vector3
{
  float                   _x;
  float                   _y;
  float                   _z;

public :
 /// constructors and stuff

};

class Point : public Vector3
{
// some BS
  Point(float _x):Vector3(float _x)
  {}
};

main()
{
   Point aPoint(3);
   Point anotherPoint(4);

   // WHY DOES THIS WORK and copy _x,_y & _z properly
   aPoint = anotherPoint;
}

Basically, I am at a loss to understand why the = for the derived class can copy _x , _y and _z , even though it shouldn't have access to them since they are private.

aPoint = anotherPoint;

This line triggers a call of Point::operator= (the assignment operator), which exists because the compiler generates a default implementation. This default implementation performs assignment operations for all members of the class, as well as calling Vector3::operator= , the assignment operator of the base class. This, in turn, is a member function of Vector3 and therefore has access to all private members, which it makes copies of.


(EDIT) A quote from the C++11 Standard to back this answer:

(§12.8/28) The implicitly-defined copy/move assignment operator for a non-union class X performs memberwise copy-/move assignment of its subobjects. The direct base classes of X are assigned first, in the order of their declaration in the base-specifier-list, and then the immediate non-static data members of X are assigned, in the order in which they were declared in the class definition. Let x be either the parameter of the function or, for the move operator, an xvalue referring to the parameter. Each subobject is assigned in the manner appropriate to its type:

— if the subobject is of class type, as if by a call to operator= with the subobject as the object expression and the corresponding subobject of x as a single function argument (as if by explicit qualification; that is, ignoring any possible virtual overriding functions in more derived classes);

— if the subobject is an array, each element is assigned, in the manner appropriate to the element type;

— if the subobject is of scalar type, the built-in assignment operator is used.

Some of the other (now partly deleted) answers mentioned the idea of a bitwise copy performed by the assignment operation. There is some truth in this: If your class or struct defines a POD (plain old data) type, it is for all practical purposes identical to a C struct. In that case, it can be copied by performing memcpy , therefore you can think of the assignment operation as being basically equivalent to a bitwise copy. But the reason why this is a valid way of thinking about it is §12.8/28 above, and that applies to non-POD types as well.

Also note that from your code it is not necessarily clear that your data type is POD. You mentioned constructors and stuff in the base class: If this involves non-trivial copy constructors, assignment operators or possibly virtual functions, then your data type is no longer POD.


About the question in the comment: In order to call the base-class assignment operator from within the derived-class implementation, just call it:

struct Base
{
};

struct Derived : Base
{
  Derived &operator=(const Derived &other)
  { Base::operator=(other); return *this; }
};

因为调用了Vector3的默认复制运算符(浅复制)。

Because the compiler generate assignment operator(s)

Point& operator=(Point const& rhs)
{
    Vector3::operator=(rhs);
    return *this;
}

Vector3& operator=(Vector3 const& rhs)
{
   // A class is a friend of irself.
   // So an object of Type A can read any other object of type A
   _x = rhs._x;
   _y = rhs._y;
   _z = rhs._z;
   return *this;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM