簡體   English   中英

在C ++中,是否可以從同級第二個派生對象訪問第一個派生對象的受保護基礎數據成員?

[英]In C++ is it possible to access a 1st derived object's protected base data member from a sibling 2nd derived object?

我正在編寫一個C ++程序,其中有兩個來自基類的派生對象,例如Derived_1和Derived_2。

在處理過程中,第一個對象將調整基礎數據成員(此處僅使用Derived_1的默認構造函數對其進行仿真)。 然后,我想從Derived_1對象中讀取該數據,並在Derived_2的構造函數中使用它來初始化Derived_2中的同一成員。

// -std=c++14
#include <iostream>

class Base {
 public:
  int data(void) { return data_; }

 protected:
  int data_{0};
};

class Derived_1 : public Base {
 public:
  Derived_1(void) { this->data_ = 42; }
};

class Derived_2 : public Base {
 public:
   // Derived_2(const Derived_1& a1) { this->data_ = a1.data_; }
};

int main() {
  Derived_1 a1;
  std::cout << "Derived_1 data: " << a1.data() << '\n';

  // Derived_2 a2 = a1;
  // std::cout << "Derived_2 data: " << a2.data() << '\n';
}

如果未注釋Derived_2中的構造函數,則會發生此錯誤:

In constructor ‘Derived_2::Derived_2(const Derived_1&)’:
error: ‘int Base::data_’ is protected within this context
Derived_2(const Derived_1& a1) { this->data_ = a1.data_; }
                                                  ^~~~~

我在SO上瀏覽了許多相關問題,試圖找到解決方案,(例如) 從基類指針到派生對象 訪問派生的私有成員函數為什么我可以通過A訪問派生的私有成員函數。基類指向派生對象的指針? 但是如果我看到了答案,我目前很難找到答案。 可能只是我的經驗不足。

感謝您幫助我解決此問題。

是的,可以通過將Derived_2成為Derived_2friendDerived_1

class Derived_1 : public Base {
    //This says that Derived_2 is a friend, which means that Derived_2
    //can access every member in Derived_1
    friend class Derived_2;
public:
    Derived_1(void) { this->data_ = 42; }
};

現在,您可以執行以下操作:

class Derived_2 : public Base {
public:
     Derived_2(const Derived_1& a1)
     { 
         //Legal, Derived_2 is a friend of Derived_1, so it can access the
         //protected member 'data_'
         this->data_ = a1.data_; 
     }
};

需要注意的是,現在, Derived_2可以修改的每一個數據成員Derived_1 ,不只是data_

第一個錯誤是派生類無法訪問在基類中聲明的data_進行使用。 要解決此問題,您需要包括以下這是您的派生類:

using Base::data_;

現在,OOP建議的是,每個對象都有與之關聯的定義明確的方法,並且沒有變量可以直接訪問。 您可以執行以下操作:

class Derived_2 : public Base {
 public:
   Derived_2(const int& a1) { this->data_ = a1; }
};

並像這樣使用它:

Derived_2 a2(a1.data());

或者,你可以聲明Derived_2作為朋友Derived_1 ,正如@ Rakete1111在他的回答中提到:

class Derived_1 : public Base {
//This says that Derived_2 is a friend, which means that Derived_2
//can access every member in Derived_1
friend class Derived_2;
public:
    Derived_1(void) { this->data_ = 42; }
};

但是,如果執行此操作,則Derived_1將直接訪問Derived_2所有變量。

編輯1(根據要求):該類的用法:

版本1:

class Derived_1 : public Base {
 using Base::data_;
 public:
  Derived_1(void) { this->data_ = 42; }
};

class Derived_2 : public Base {
 using Base::data_; 
 public:
    Derived_2(const Derived_1& a1) { this->data_ = a1.data(); }
};

版本2:

//Declaration of Derived_2 here for Derived_1 
//to know that a class with such a name exists
class Derived_2 : public Base;

class Derived_1 : public Base {
 using Base::data_;
 friend class Derived_2;
 public:
  Derived_1(void) { this->data_ = 42; }
};

class Derived_2 : public Base {
 using Base::data_; 
 public:
    Derived_2(const Derived_1& a1) { this->data_ = a1.data_; }
};

派生類只能訪問其自己的基類子對象的受保護成員。 他們無權訪問其他類的受基礎保護的成員,即使該基礎與其自身的類型相同。

可能的解決方案:

  • 聲明Base::data_ public。
  • 或宣布Derived_2作為朋友Derived_1

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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