我有以下设计: - 一个有A级受保护成员的A类 - 一个继承自A并具有指向C类对象的指针的B类 - 需要访问A类成员的一个C类
class A {
public:
A() : _member(0) {}
~A() { delete _member }
protected:
M _member;
}
class B : public A {
public:
B(){}
~B(){}
protected:
C* c;
}
class C {
// C needs to have access to _member
}
哪种设计更适合解决此问题?
答案 0 :(得分:1)
让C
成为friend
A
:
class A {
friend class C;
/*and so on*/
然后C
可以查看A
中的所有成员变量和函数,即使它们是private
。
答案 1 :(得分:1)
在纯OO术语中,允许类直接访问另一个类的内部字段是不好的做法。
尽管如此,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
。
但是,如前所述,任何派生自C的类都无法访问_member
,因为友谊不会被继承,因此需要更全面的解决方案:
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;
}
通过这种方式,没有派生自A的类提供对_member的直接访问,并且没有派生自C的类具有直接访问权限,但仍然可以通过C的受保护API访问成员变量。这也可以防止其他外部对象访问它。