[英]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.