简体   繁体   English

默认赋值运算符可以访问基类的私有成员

[英]Default assignment operator has access to private members of base class

My problem is very easily explained by this example : 这个例子很容易解释我的问题:

http://pastebin.com/VDBE3miY 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. 基本上,我不知所措,为什么派生类的=为什么可以复制_x_y_z ,即使由于它们是私有的也无法访问它们。

aPoint = anotherPoint;

This line triggers a call of Point::operator= (the assignment operator), which exists because the compiler generates a default implementation. 该行触发Point::operator= (赋值运算符)的调用,该调用之所以存在是因为编译器会生成默认实现。 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. 此默认实现对类的所有成员执行赋值操作,并调用Vector3::operator= (基类的赋值运算符)。 This, in turn, is a member function of Vector3 and therefore has access to all private members, which it makes copies of. 这又是Vector3的成员函数,因此可以访问所有私有成员,并对其进行复制。


(EDIT) A quote from the C++11 Standard to back this answer: (编辑)来自C ++ 11标准的引用以支持此答案:

(§12.8/28) The implicitly-defined copy/move assignment operator for a non-union class X performs memberwise copy-/move assignment of its subobjects. (第12.8 / 28节)非工会类X的隐式定义的复制/移动分配操作符对其子对象执行成员式复制/移动分配。 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. X的直接基类首先按照它们在base-specifier-list中的声明顺序进行分配,然后按在类定义中声明的顺序分配X的直接非静态数据成员。 。 Let x be either the parameter of the function or, for the move operator, an xvalue referring to the parameter. 令x为函数的参数,或者对于move运算符,为引用该参数的xvalue。 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); —如果子对象是类类型,则好像是通过调用operator =来实现的,子对象作为对象表达式,x的对应子对象作为单个函数参数(就像通过显式限定;也就是说,忽略任何可能的虚拟覆盖)更多派生类中的功能);

— 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. 这样做有一个道理:如果您的类或结构定义了POD(普通旧数据)类型,则在所有实际应用中它都与C结构相同。 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. 在那种情况下,可以通过执行memcpy复制它,因此您可以认为分配操作基本上等效于按位复制。 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. 但是,这是一种有效的思考方式,其原因在于上文的§12.8/ 28,它也适用于非POD类型。

Also note that from your code it is not necessarily clear that your data type is POD. 还要注意,从您的代码中,不一定清楚您的数据类型是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. 您在基类中提到了构造函数和相关内容 :如果涉及非平凡的拷贝构造函数,赋值运算符或可能的虚函数,则您的数据类型不再是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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在复制赋值运算符中分配基类成员 - Assigning base class members in copy assignment operator 内部类中的默认赋值运算符,带有引用成员 - Default assignment operator in inner class with reference members 朋友功能无法访问私人班级成员 - friend function has no access to private class members 为什么我不能在 operator&lt;&lt; 中访问 Box 类的私有成员? - Why can't I access private members of class Box in operator<<? 访问类的私有成员? - Access a class' private members? ostream &lt;&lt;带有模板类的运算符,无法访问私有成员 - ostream << operator with template class, cannot access private members 在重载&lt;&lt;运算符时获得访问私有类成员的问题 - Problems gaining access to the private class members while overloading the << operator 无法使用朋友类从基类访问私有成员 - Cannot access private members from base class using friend classes 在赋值运算符中无法访问基类的受保护方法 - Cannot access base class' protected method in assignment operator std :: unique_ptr编译器错误:派生类的成员无法访问基类的私有成员 - std::unique_ptr compiler error: Members of a derived class cannot access private members of a base class
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM