簡體   English   中英

默認賦值運算符可以訪問基類的私有成員

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

這個例子很容易解釋我的問題:

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;
}

基本上,我不知所措,為什么派生類的=為什么可以復制_x_y_z ,即使由於它們是私有的也無法訪問它們。

aPoint = anotherPoint;

該行觸發Point::operator= (賦值運算符)的調用,該調用之所以存在是因為編譯器會生成默認實現。 此默認實現對類的所有成員執行賦值操作,並調用Vector3::operator= (基類的賦值運算符)。 這又是Vector3的成員函數,因此可以訪問所有私有成員,並對其進行復制。


(編輯)來自C ++ 11標准的引用以支持此答案:

(第12.8 / 28節)非工會類X的隱式定義的復制/移動分配操作符對其子對象執行成員式復制/移動分配。 X的直接基類首先按照它們在base-specifier-list中的聲明順序進行分配,然后按在類定義中聲明的順序分配X的直接非靜態數據成員。 。 令x為函數的參數,或者對於move運算符,為引用該參數的xvalue。 每個子對象都以適合其類型的方式分配:

—如果子對象是類類型,則好像是通過調用operator =來實現的,子對象作為對象表達式,x的對應子對象作為單個函數參數(就像通過顯式限定;也就是說,忽略任何可能的虛擬覆蓋)更多派生類中的功能);

—如果子對象是數組,則以適合元素類型的方式分配每個元素;

—如果子對象是標量類型,則使用內置的賦值運算符。

其他一些答案(現在已部分刪除)提到了通過賦值操作執行按位復制的想法。 這樣做有一個道理:如果您的類或結構定義了POD(普通舊數據)類型,則在所有實際應用中它都與C結構相同。 在那種情況下,可以通過執行memcpy復制它,因此您可以認為分配操作基本上等效於按位復制。 但是,這是一種有效的思考方式,其原因在於上文的§12.8/ 28,它也適用於非POD類型。

還要注意,從您的代碼中,不一定清楚您的數據類型是POD。 您在基類中提到了構造函數和相關內容 :如果涉及非平凡的拷貝構造函數,賦值運算符或可能的虛函數,則您的數據類型不再是POD。


關於注釋中的問題:為了從派生類實現中調用基類賦值運算符,只需調用它:

struct Base
{
};

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

因為調用了Vector3的默認復制運算符(淺復制)。

因為編譯器會生成賦值運算符

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM