我在一家制造工厂工作,该工厂使用大型 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
和 obj2
成为 C
类中的 public
成员似乎并不不安全,因为A
和 B
类各自安全地处理自己的成员变量的获取和设置。
我能想到的这样做的唯一缺点是调用函数的 C
类的任何实例都需要执行诸如 obj.obj1.get_a() 之类的操作
而不仅仅是 obj.get_a()
但这似乎比拥有私有(private) A
和 B
对象实例带来的不便要少得多在 C
类中,然后需要手动“中继”其所有成员函数。
我意识到,对于这个简单的示例,它并没有太多额外的代码,但对于我公司使用的这个大型项目,它确实添加了数万行代码。
我错过了什么吗?
最佳答案
原因可能有很多。其一如下:
假设您编写了一个函数,该函数对成员 a
执行某些操作。您希望相同的代码接受 A
和 C
。您的函数可能如下所示:
template <typename T>
void foo(T& t) {
std::cout << " a = " << t.get_a();
}
这不适用于您的 C
,因为它具有不同的接口(interface)。
封装有它的好处,但我同意你的观点,为了封装而封装通常会导致更多的代码,而且通常不会有其他结果。
一般来说,不鼓励强制调用代码编写诸如 obj.obj1.get_a()
之类的内容,因为它会泄露实现细节。如果您更改了例如 a
的类型,那么您的 C
无法控制该更改。另一方面,如果原始代码中a
从int
更改为double
,则C
可以决定是否保留int
接口(interface)并进行一些转换(如果适用)或更改其接口(interface)。
关于C++ 中继嵌套类中的成员函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47062165/