C ++在嵌套类中中继成员函数?

时间:2017-11-01 19:20:02

标签: c++ class nested

我在一家制造工厂工作,该工厂使用大型C ++项目来实现制造过程的自动化。

我看到一个地方的某种做法,似乎只是让代码变得不必要地长,我想知道是否有使用这种做法的具体原因。

请参阅下文,了解演示此做法的简化示例。

第一档:

class A {

private:
   int a;

public:
   int get_a()
   { return a; }

   void set_a(int arg)
   { a = arg; }
};

第二档:

class B {

private:
   int b;

public:
   int get_b()
   { return b; }

   void set_b(int arg)
   { b = arg; }
};

第三档:

class C {

private:
   A obj1;
   B obj2;

public:
   int get_a()
   { return obj1.get_a(); }

   int get_b()
   { return obj2.get_b(); }

   void set_a(int arg)
   { obj1.set_a(arg); }

   void set_b(int arg)
   { obj2.set_b(arg); }
};

在我看来,设计理念的微小变化可能会大大减少第三个文件中的代码量。像这样:

class C {

public:
   A obj1;
   B obj2;

};

obj1班级中obj2public成员C似乎并不安全,因为AB每个类都安全地处理它们自己的成员变量的获取和设置。

我能想到这样做的唯一缺点是调用函数的C类的任何实例都需要执行类似obj.obj1.get_a()而不仅仅是obj.get_a()的操作但这似乎比在A类中拥有私有BC对象实例,然后手动需要“中继”其所有成员函数更不方便。

我意识到这个简单的例子,它没有多少额外的代码,但是对于我公司使用的这个大型项目,它增加了数万代码行。

我错过了什么吗?

2 个答案:

答案 0 :(得分:1)

可能有很多原因。一个是以下内容:

想象一下,你编写了一个与成员a做某事的函数。您希望相同的代码接受A以及C。你的功能可能如下所示:

template <typename T>
void foo(T& t) {
    std::cout << " a = " << t.get_a();
}

这不适用于您的C,因为它有不同的界面。

封装有其好处,但我同意你的看法,为了封装,封装通常会导致更多代码,而且通常只会产生更多代码。

通常,不鼓励强制调用代码来编写类似obj.obj1.get_a()的内容,因为它会显示实现细节。如果您更改了a的类型,那么您的C无法控制该更改。另一方面,如果原始代码aint更改为double,则C可以决定是否保留int界面并进行一些转换(如果适用)或改变其界面。

答案 1 :(得分:1)

它确实添加了一些额外的代码,但重要的是你的界面。一个类有责任,它拥有的成员是实现细节。如果您公开内部对象并强制用户获取对象,则对其进行调用&#34;如果您只提供一个为用户完成工作的界面,那么您将调用者与实现相结合。作为一个类比,[借用维基百科]当一个人想要一只狗走路时,一个人不会让狗的腿直接走路;相反,一个命令狗然后命令它自己的腿。

Law of Demeter / Wikipedia

  

更正式地说,函数的Demeter法则要求对象O的方法m只能调用以下类型对象的方法:

  • O本身
  • m参数
  • 在m
  • 中创建/实例化的任何对象
  • O的直接组件对象
  • 一个全局变量,可由O访问,范围为m
  

特别是,对象应该避免调用另一个方法返回的成员对象的方法。对于许多使用点作为字段标识符的现代面向对象语言,法律可简单地表示为&#34;仅使用一个点&#34;。也就是说,代码a.b.c.Method()违反了a.b.Method()没有的规律。