题
我试图正确地封装一类A,它应该仅由B类操作上。
然而,我想从B类继承。
有一个朋友B不工作 - 友好不被继承
什么是完成我想要的东西,还是我犯了一个错误?普遍接受的方式。
要给你更多的色彩,类A代表一个复杂的系统的状态。它应该只由B,其是可应用到改变类A的状态的动作进行修改。
解决方案
我假设你想允许B的后裔一个直接访问?如果A和B是紧耦合的,你可以让乙本身内的一个受保护的类定义,而不是作为一个独立的定义。 E.G。
class B
{
protected:
class A
{
};
};
另一个想法是创建基于B的受保护方法即委托其行动A. E.G。
class A
{
friend class B;
private:
void DoSomething();
};
class B
{
protected:
void DoSomething(A& a) { a.DoSomething(); }
};
其他提示
这听起来像你可能需要做一个重新设计;你的A级所代表的国家,但你的B类代表一组动作。有一个关系的存在,但它不是一个继承关系。我建议组成;您想了解更多的比ISA关系的公会关系,据我可以告诉。
如果我理解正确的话,你想拥有B'STRONG>和它的衍生品即可访问内部实现A级的,是吧?
不幸的是,C ++没有“内部”的保护的水平,如C#和Java语言posses
概念您可以考虑使用私有实现范式(平普尔) - 也被称为不透明指针,使用公共访问级别的系统内公开功能,A和B的消费者不会看到。
藏在心里的是,最容易做的事情是添加受保护的方法到B,让访问的等效特点那就需要。这将打开封装只是B的子类。
在最简单的方法来做到这是简单地有乙包含的A:
类B { 保护: 一个A_; };
然后,你可以写一个C类其中的B继承并能够操纵A.若C不应该是能够做到的事情任意到A,然后进行一个私人的B,提供B中受保护的方法该C可使用做批准事情到A,像这样:
类B { 私人的: 一个A_; 保护: 无效doSomethingToA(); };
遏制是去(类B包含类型A的私有成员),除非B需要重写所述的一些虚拟包,所述方法在这种情况下的私有继承的是最接近。
我看不出你为什么会想继承。使在私人和朋友B.乙一切然后具有其中一个构件可以自由地操纵。
在描述这个问题的方法它听起来更像组合物而不是继承。 E.g。
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(属性)或类似,句法疼痛可以得到缓解。
如果你想确保仅有B上的一个操作,使私人的实例和暴露的B受保护的接口添加到其后代。
class A
{
public:
void foo() {}
};
class B
{
private:
A a;
protected:
void CallAFoo() { a.foo() };
};
class C : public B
{
void goo() { CallAFoo(); }
};
这是我从你的问题明白了,你会需要一些多态性。你需要一个摘要 A类和B类继承类A.此外,在保护关键字允许继承的类来访问某些信息,而在同一时间拒绝访问其他任何事情。这里是一个小例子:
// 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 (取代码包含多态性和抽象类信息太)。