C ++封装技术

时间:2009-07-08 18:11:55

标签: c++ inheritance encapsulation

我正在尝试正确封装A类,它只能由B类操作。

但是,我想继承B类。

让朋友B不能工作 - 友谊不会被继承。

什么是普遍接受的完成我想要的方式,或者我犯了错误?

为了给你更多颜色,A类代表复杂系统的状态。它只能由B修改,这是可以应用于改变A类状态的动作。

11 个答案:

答案 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(); }
};