純粋なオブジェクト指向の用語では、クラスが別のクラスの内部フィールドに直接アクセスできるようにすることは悪い習慣です。つまり、C++は純粋なOO言語ではなく、これを(OOからの他の重要な逸脱の中でも)許しています。
プライベートメンバーに別のクラスへのアクセスを許可するには、そのクラスをフレンドに指定する必要があります。ただし、フレンドシップは派生クラスには渡されないため、クラスを必要なタイプにアップキャストする必要があります。
これはあなたの最も簡単な解決策である。このように
class A {
public:
A() : _member(0) {}
~A() { delete _member }
protected:
friend class C;
M _member;
}
class B : public A {
public:
B(){ c = new C(this); } // this call will cast the B* to an A* (important)
~B(){ delete c;}
protected:
C* c;
}
class C {
public:
C(A* a) { _a->_member = new M(); } //Now C can directly access _member in A
}
、A
から導出された任意のオブジェクトは、バックA*
になって、_member
にアクセスするために使用することができます。
しかし先に述べたように、友情が継承されないよう、_member
へのアクセスを得るませんCから派生したクラスは、これより包括的なソリューションが必要とされています。このように
class M {
public:
void Foo() { printf("Foo called\n"); }
};
class A {
M* m;
friend class C;
public:
A():m(0) { ; }
};
class B :public A {
int id;
public:
B() { id = 0; }
};
class C {
public:
C() { _a = 0; }
C(A* a) { _a = a; }
protected:
M* getM() { return _a->m; }
void setM(M* m_) { _a->m = m_; }
private:
A* _a;
};
class D : public C {
public:
D(B* b): C(b) {
}
void Foo() {
setM(new M());
getM()->Foo();
delete getM();
setM(nullptr);
}
};
int main()
{
B* b = new B();
D d(b);
d.Foo();
delete b;
getchar();
return 0;
}
は、何のクラスは派生しませんfrom Aは_memberへの直接アクセスを提供し、Cから派生したクラスは直接アクセスできませんが、メンバ変数はCの保護されたAPIを介してアクセスできます。これにより、他の外部オブジェクトがそのオブジェクトにアクセスすることも防止されます。
標準的な回答は、たとえば、提供することによって_メンバーへのアクセスを管理することです。セッターメソッドとゲッターメソッド。 CはAまたはBとの関係がないように継承チェーンが構築されているため、「友人」はコード全体のアクセスパターンを汚染し、他の意図しないアクセス権を付与する可能性があります。 – StarShine