我正在尝试正确封装A类,它只能由B类操作。
但是,我想继承B类。
让朋友B不能工作 - 友谊不会被继承。
什么是普遍接受的完成我想要的方式,或者我犯了错误?
为了给你更多颜色,A类代表复杂系统的状态。它只能由B修改,这是可以应用于改变A类状态的动作。
答案 0 :(得分:4)
听起来你可能需要重新设计;你的A类代表一个国家,但你的B类代表一组行动。那里有一段关系,但这不是继承关系。我建议组成;据我所知,你想要更多的HASA关系而不是ISA关系。
答案 1 :(得分:3)
如果我理解正确,你想让B 及其衍生物能够访问A类的内部实现,是吗?
不幸的是,C ++没有像C#和Java这样的语言拥有的“内部”保护级别的概念。
您可以考虑使用private implementation paradigm(pimpl) - 也称为不透明指针,使用公共访问级别公开系统中的功能,A和B的使用者不会看到。
答案 2 :(得分:3)
我假设你想让B的后代直接访问A?如果A和B紧密耦合,则可以在A本身内使A成为受保护的类定义,而不是独立定义。 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(); }
};
答案 3 :(得分:2)
最简单的方法就是让B包含A:
B班{ 保护: 一个a_; };
然后,您可以编写一个继承自B并且能够操作A的C类。如果C不能对A做任意事情,那么在B中使A成为私有并在B中提供受保护的方法C可以用来对A做批准的事情,如下:
B班{ 私人的: 一个a_; 保护: void doSomethingToA(); };
答案 4 :(得分:2)
保持一切正常,最简单的方法是向B添加受保护的方法,以便访问其所需的A等效功能。这将打开封装到B的子类。
答案 5 :(得分:1)
包含是要走的路(B类包含A类的私有成员),除非B需要覆盖A中的某些虚拟,在这种情况下,私有继承是最接近的东西。
答案 6 :(得分:0)
我无法理解你为什么要继承。把所有东西都放在私人和朋友B.然后有一个A的成员,它可以自由操纵。
答案 7 :(得分:0)
你描述它的方式听起来更像是构图而不是继承。 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 { }
答案 8 :(得分:0)
使用您提供的一些信息:
B类应负责保留A类的不变量,而B类应该是操纵A的唯一方法。任何客户端派生类或调用者都不应该知道A存在。
(从设计POV开始,甚至没有需要来存在A,但我遇到了足够的实际原因,我不会反对你这样的分离;))
这可能需要编写大量样板代码,或者需要一些界面技巧。例如如果允许客户端使用A类来查询信息而不是修改它,B可以分发一个const&聚合A.使用支持__declspec(属性)或类似的编译器,可以减轻语法上的痛苦。
答案 9 :(得分:0)
根据我对你的问题的理解,你需要一些多态。您需要一个抽象类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(包含有关多态性和抽象类的信息)。
答案 10 :(得分:0)
如果你想确保只有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(); }
};