簡體   English   中英

為方便起見,我應該避免將私有字段變量公開嗎?

[英]Should I avoid making private field variable public for convenience?

我有兩個對象,A和B.現在,B將A存儲為本地類變量。

class B
{
    A myA;
} 

現在,B有一堆方法使用它的內部myA做一些事情,我可以使用這些方法,因為它們是公開的。

但有時,我需要使用myA本身。 所以我做的是公開,然后我可以寫myB.myA.someMethodFromA()

這樣可以,還是風格不好? 我的意思是,我知道我可以通過B類中的方法為myA提供間接訪問器,但是當我可以直接訪問myA時,這似乎是不必要的。

例如,如果myA有一個方法doStuffviaA ,我寧願說myB.myA.doStuffViaA() ,而不是首先要在B中寫一個方法

void doStuffViaB() { myA.doStuffViaB() }

但是,當然讓myA公開意味着它可以在沒有B知道的情況下進行更改。 該怎么辦?

是的,將其public可以避免封裝,代碼可能會崩潰,從而使您的對象進入一個定義不明確的狀態。

供應中途的房屋選擇

const A& getMyA() const
{
    return myA;
}

從那時起,至少,如果使用此函數訪問,則只能在myA成員上執行const函數。 當然,我希望doStuffViaA const ,然后你就寫了

myB.getMyA().someMethodFromA();

該怎么辦?

它取決於並且實際上完全取決於具體情況。 一般來說,我建議你

  • 僅在普通,不變的struct使用公共數據成員( C2
  • 一旦你有一些不變量,使用一個class ,使數據成員privateC2C8
  • 盡可能避免使用吸氣劑。

如果后者不可能(例如由於“設計限制”或對“便利性”的強烈渴望),您可以在@ Bathsheba的答案中提供一個吸氣劑。 或者,您可以將指向A成員函數的指針或接受A&參數的函數傳遞給具有關聯函數參數的B的成員函數模板,例如

#include <functional>

class B {
   public:
      template <class MemberFct, class ...Args>
      decltype(auto) invokeOnA(MemberFct fct, Args&&... args)
      {
         return std::invoke(fct, a, std::forward<Args>(args)...);
      }

   private:
      A a;
};

請注意,這需要C ++ 17。 給定成員函數A::doStuff(int) ,可以實例化該模板並使用

B b;

b.invokeOnA(&A::doStuff, 42);
b.invokeOnA([](A& a){ a.doStuff(42); });

它通過另一個間接級別並且沒有getter方法來解決問題。 但請注意,該方法在定性上與提供getter方法非常相似,即,具有花哨的函數模板並不能使您無法理解為什么必須在特定用例中破壞封裝。

我想你已經到了關鍵點:

但是,當然讓myA公開意味着它可以在沒有B知道的情況下進行更改。 該怎么辦?

使成員公開或私人不僅僅是為了方便。 問問自己:如果成員是公共的,那么我的班級依賴的不變量是否會破壞?

只有你絕對可以用“否”回答這個問題,你才能公開會員。 但是,在這種情況下你可以問:為什么它無論如何都是這個類的成員?

考慮這個簡單的破解示例:

struct foo { 
    int a,b,sum;
    foo(int a,int b) : a(a), b(b), sum(a+b) {}
};

為確保sum == a+b始終成立,所有成員都不應公開。 另一方面,考慮std::pair ,它只是一個數據結構,因此firstsecond公開都沒問題。

暫無
暫無

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

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