3

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

但是,我想从 B 类继承。

拥有朋友 B 是行不通的——友谊不是遗传的。

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

为了给你更多的色彩,A 类代表一个复杂系统的状态。它只能由 B 修改,这些操作可用于更改 A 类的状态。

4

11 回答 11

4

听起来您可能需要重新设计;您的 A 类代表一个州,但您的 B 类代表一组动作。那里有关系,但不是继承关系。我建议作文;据我所知,你想要更多的 HASA 关系而不是 ISA 关系。

于 2009-07-08T18:17:07.827 回答
3

如果我对您的理解正确,您希望拥有 B及其衍生产品以访问 A 类的内部实现,是吗?

不幸的是,C++ 没有像 C# 和 Java 这样的语言所拥有的“内部”保护级别的概念。

您可以考虑使用私有实现范例(pimpl) - 也称为不透明指针,以使用公共访问级别公开系统内的功能,而 A 和 B 的使用者不会看到。

于 2009-07-08T18:22:18.987 回答
3

我假设您想允许 B 的后代直接访问 A?如果 A 和 B 紧密耦合,则可以使 A 在 B 本身内成为受保护的类定义,而不是成为独立的定义。例如

class B
{
protected:
    class A
    {
    };
};

另一个想法是在 B 上创建受保护的方法,将它们的操作委托给 AEG

class A
{
friend class B;
private:
    void DoSomething();
};

class B
{
protected:
    void DoSomething(A& a) { a.DoSomething(); }
};
于 2009-07-08T18:29:35.100 回答
2

最直接的方法就是让 B 包含一个 A:

B类{保护:A a_; };

然后,您可以编写一个从 B 继承并能够操作 A 的类 C。如果 C 不应该对 A 做任意事情,那么将 A 在 B 中设为私有,并在 B 中提供 C 可以的受保护方法用来对 A 做批准的事情,像这样:

B类{私人:A a_; 受保护:无效doSomethingToA();};

于 2009-07-08T18:18:35.733 回答
2

保持一切不变,最简单的做法是向 B 添加受保护的方法,以访问它需要的 A 的等效功能。这打开了对 B 的子类的封装。

于 2009-07-08T18:22:05.040 回答
1

包含是要走的路(B 类包含 A 类型的私有成员),除非 B 需要覆盖 A 中的一些虚拟,在这种情况下,私有继承是最接近的事情。

于 2009-07-08T18:26:40.567 回答
0

我不明白你为什么要继承。将 A 中的所有内容设为私有并设为好友 B。然后 B 拥有 A 的成员,它可以自由操作。

于 2009-07-08T18:21:05.447 回答
0

你描述它的方式听起来更像是组合而不是继承。例如

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 { }
于 2009-07-08T18:23:28.763 回答
0

使用您提供的信息:

B 类应该负责保留 A 类的不变量,而 B 类应该是操作 A 的唯一方法。任何客户端(派生类或调用者)都不需要知道 A 的存在。

(从设计 POV 来看,A 甚至不需要存在,但我已经遇到了足够多的实际原因导致这种分离,所以我不会反对你;))

这可能需要编写大量样板代码,或者需要一些接口技巧。例如,如果允许客户端使用类 A 来查询信息但不能修改它,B 可以将 const & 分发给聚合的 A。使用支持 __declspec(property) 或类似的编译器,可以减轻语法上的痛苦。

于 2009-07-08T18:34:49.630 回答
0

根据我从您的问题中了解到的情况,您将需要一些polymorphism。您需要一个抽象类 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的代码(也包含有关多态性和抽象类的信息)。

于 2009-07-08T19:00:06.960 回答
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(); }
};
于 2009-07-08T19:13:02.657 回答