复杂的对象在另一个里面

时间:2018-04-19 07:17:07

标签: c++ design-patterns

我有以下课程

class A {
private:
   B b;
public:
   A();
}

class B {
public:
   void foo();
   void bar();
   void foz();
   ........
}

B有很多方法。有时A类的“客户”需要使用类B的方法。我可以返回B的引用,但在这种情况下我应该返回一个const引用,因为返回私有对象的非const引用是不好的节目。如果引用是const,则不能调用foo,bar等,因为它们不是const。因此,唯一的“干净”方式似乎是在A中使用委托给B重新创建相同的接口。但是这种方法并不是很好,因为我应该重新创建A中的所有接口。作为替代方案,我可以将B设置为A中的公共,但它对我来说似乎很“奇怪”。在这种情况下我该怎么做?

3 个答案:

答案 0 :(得分:2)

这主要是一个封装问题,以及您希望在A类公共接口中做广告

如果B类也是 public 类 - 读取通常可以由A类用户使用,而不是库或框架内部的类 - 如果您想要存在B子对象存在于A类的公共文档中,如果要允许对B对象进行任何操作,则可以安全地提供getter。

如果上述任何条件都是错误的,那么getter会破坏封装,你最好在A类中定义委托方法。

根据一般设计,仅使用您希望从A类允许的方法声明接口类(比如说C)并使B成为C的子类是有意义的。然后你可以安全地声明一个getter返回一个C对象的引用:

class C {
public:
   void foo();  // optionally virtual or pure virtual...
   void bar();
   void foz();
};

class B: public C {
....    // other members not relevant for what is public for A users
};

class A {
private:
   B b;
public:
   A();
   C& getB() {
       return b;
   }
};

答案 1 :(得分:0)

解决方案1.您创建一个getb()并返回对B的引用。特别是在您的情况下编程也不错。
解决方案2.为b的每个对应函数创建接口函数并调用它们。

void A::foo()
{
    b.foo();
}

答案 2 :(得分:-2)

您可以将数据成员protected设为private而不是private。文档说受保护的成员不像public成员那样私有,只有声明它们的类的成员才能访问它们,但它们不像protected成员那样公开,可以通过任何功能访问protected成员(无论他们是方法成员的数据成员)都会为您所寻找的角色提供服务:无法从任何地方访问这些角色(安全编码实践),但您仍然可以在 clean < / em>有意义的方式:

  1. 如果A类具有B类属性,则可以访问B&#39; s publicfriend成员
  2. protected个函数可以访问public个类的friendprotected个成员。
  3. 当在基类名称之前时,#include <iostream> using std::cout; using std::endl; class B { public: void foo() { cout << "foo" << endl; }; void bar() { cout << "bar" << endl; }; void foz() { cout << "foz" << endl; }; }; class A { protected: // <===== THIS IS THE SIGNIFICANT BIT B b; public: A() { b.foo(); b.bar(); b.foz(); cout << "A constructor" << endl; }; }; int main(int argc, char** argv) { A myA; return 0; } 关键字指定基类的公共成员和受保护成员是其派生类的受保护成员。
  4. 在这里,您对列表的第一项感兴趣:您可以访问B&#39;来自A的方法;但B仍然有保障措施。

    当我运行以下代码(改编自您的代码)时:

    foo
    bar
    foz
    A constructor
    

    我得到以下控制台输出:

    if let location = (data["location"] as? Array<[String:Any]>).first, let str = location["name"] as? String {
    
        print(str)
    }
    

    这表明我可以从A。

    访问B&B的方法