簡體   English   中英

C ++封裝技術

[英]C++ Encapsulation Techniques

我正在嘗試正確封裝一個A類,它只能由B類操作。

但是,我想繼承B班。

有一個朋友B不起作用 - 友誼不是繼承的。

什么是普遍接受的完成我想要的方式,或者我犯了錯誤?

為了給你更多顏色,A類代表復雜系統的狀態。 它只應由B修改,這是可以應用於更改A類狀態的動作。

聽起來你可能需要重新設計; 你的A類代表一個國家,但你的B類代表一組行動。 那里有一段關系,但這不是繼承關系。 我建議組成; 據我所知,你想要更多的HASA關系而不是ISA關系。

如果我理解正確,你想讓B 和它的衍生物能夠訪問A類的內部實現,是嗎?

不幸的是,C ++沒有像C#和Java這樣的語言擁有的“內部”保護級別的概念。

您可以考慮使用私有實現范例 (pimpl) - 也稱為不透明指針,使用公共訪問級別公開系統中的功能,A和B的使用者將看不到。

我假設你想讓B的后代直接訪問A? 如果A和B緊密耦合,則可以在A本身內使A成為受保護的類定義,而不是獨立定義。 例如

class B
{
protected:
    class A
    {
    };
};

另一個想法是在B上創建受保護的方法,將其行動委托給AEG

class A
{
friend class B;
private:
    void DoSomething();
};

class B
{
protected:
    void DoSomething(A& a) { a.DoSomething(); }
};

最直接的方法是讓B包含A:

B級{保護:A a_; };

然后,你可以編寫一個繼承自B並且能夠操作A的C類。如果C不能對A做任意事情,那么在B中使A成為私有並在B中提供C可以保護的方法用來做批准的東西到A,像這樣:

B級{私人:A a_; protected:void doSomethingToA(); };

保持一切正常,最簡單的方法是向B添加受保護的方法,以便訪問其所需的A等效功能。 這打開了封裝到B的子類。

包含是要走的路(B類包含A類的私有成員),除非B需要覆蓋A中的一些虛擬,在這種情況下是最接近的東西。

我不明白你為什么要繼承。 在A私人和朋友B. B然后有一個A成員,它可以自由操縱。

你描述它的方式聽起來更像是構圖而不是繼承。 例如

class ComplexMachine {
  public:
    setState(int state);
};

class Operator {
   public:
   Operator(ComplexMachine & m) :_m(m) {};

   void drive() { _m->setState(1); }
   void turn() { _m->setState(2); }
   void stop() { _m->setState(0); }

   private:
   ComplexMachine _m;   
};

class SmoothOperator : public Operator { }

使用您提供的一些信息:

B類應該負責保留A類的不變量,而B類應該是操縱A的唯一方法。任何客戶端派生類或調用者都不應該知道A存在。

(從設計POV來看,甚至不需要 A存在,但我遇到了足夠的實際原因,這種分離我不會反對你;))

這可能需要編寫大量的樣板代碼,或者接口上的一些技巧。 例如,如果允許客戶端使用類A來查詢信息但不允許修改它,則B可以將const發送給聚合的A.使用支持__declspec(屬性)或類似的編譯器,可以減輕語法上的痛苦。

根據我對你的問題的理解,你需要一些多態性 您需要一個抽象類A,B類繼承A類。此外, protected關鍵字允許繼承的類可以訪問某些信息,同時拒絕訪問其他任何信息。 這是一個小例子:

// dynamic allocation and polymorphism
#include <iostream>
using namespace std;

class CPolygon {
  protected:
    int width, height;
  public:
    void set_values (int a, int b)
      { width=a; height=b; }
    virtual int area (void) =0;
    void printarea (void)
      { cout << this->area() << endl; }
  };

class CRectangle: public CPolygon {
  public:
    int area (void)
      { return (width * height); }
  };

class CTriangle: public CPolygon {
  public:
    int area (void)
      { return (width * height / 2); }
  };

int main () {
  CPolygon * ppoly1 = new CRectangle;
  CPolygon * ppoly2 = new CTriangle;
  ppoly1->set_values (4,5);
  ppoly2->set_values (4,5);
  ppoly1->printarea();
  ppoly2->printarea();
  delete ppoly1;
  delete ppoly2;
  return 0;
}

代碼取自cplusplus.com (包含有關多態性和抽象類的信息)。

如果您想確保只有B在A上運行,請將A實例設為私有,並將受保護的接口從B暴露給它的后代。

class A
{
  public:
    void foo() {}
};

class B
{
  private:
    A a;

  protected:
    void CallAFoo() { a.foo() };
};

class C : public B
{
    void goo() { CallAFoo(); }
};

暫無
暫無

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

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