C++ 为了方便起见,我应该避免将私有字段变量公开吗?
我有两个对象,A和B。现在,B将A存储为局部类变量C++ 为了方便起见,我应该避免将私有字段变量公开吗?,c++,design-patterns,C++,Design Patterns,我有两个对象,A和B。现在,B将A存储为局部类变量 class B { A myA; } 现在,B有一堆方法,它们使用内部的myA来做一些事情,我可以使用这些方法,因为它们是公共的 但有时,我需要使用myA本身。所以我所做的就是将它公开,然后我可以编写myB.myA.someMethodFromA() 这样行吗,还是风格不好?我的意思是,我知道我可以通过B类中的方法为myA提供间接访问器,但当我可以直接访问myA时,这似乎是不必要的 例如,如果myA有一个方法dostufviaa,我
class B
{
A myA;
}
现在,B有一堆方法,它们使用内部的myA
来做一些事情,我可以使用这些方法,因为它们是公共的
但有时,我需要使用myA
本身。所以我所做的就是将它公开,然后我可以编写myB.myA.someMethodFromA()
这样行吗,还是风格不好?我的意思是,我知道我可以通过B类中的方法为myA
提供间接访问器,但当我可以直接访问myA
时,这似乎是不必要的
例如,如果myA
有一个方法dostufviaa
,我宁愿说myB.myA.dostufviaa()
,而不是先在B中写一个方法
void dostufviab(){myA.dostufviab()}
但是,当然,将
myA
公开意味着它可以在B
不知道的情况下进行更改。怎么办?是的,将其公开可以避免封装,代码可能会悄悄进入,从而使对象进入定义不清的状态
中途之家的选择是提供
const A& getMyA() const
{
return myA;
}
从那时起,如果使用此功能访问myA
成员,则至少只能对其执行const
功能。当然,我希望dostufviaa
是const
,然后你会写
myB.getMyA().someMethodFromA();
怎么办
这取决于,事实上相当取决于具体情况。一般来说,我建议你
- 仅在普通、不变的自由
s()中使用公共数据成员struct
- 使用
一旦有了一些不变量,就将数据成员类
(,)设为私有
- 尽可能避免使用吸气剂
a
成员函数或接受a&
参数的函数的指针传递给B
的成员函数模板以及相关函数参数,例如
#include <functional>
class B {
public:
template <class MemberFct, class ...Args>
decltype(auto) invokeOnA(MemberFct fct, Args&&... args)
{
return std::invoke(fct, a, std::forward<Args>(args)...);
}
private:
A a;
};
它通过另一个间接层次解决了问题,并且没有getter方法。但是,请注意,该方法在性质上与提供getter方法非常相似,即,拥有一个奇特的函数模板并不能让您从为什么有必要在特定用例中破坏封装的理由中解脱出来。我认为您已经抓住了关键点: 但是,当然,将myA公之于众意味着它可以在无需修改的情况下进行更改 B知道这件事。怎么办 将成员公开或私有不仅仅是为了方便。扪心自问:如果成员是公共的,我的类所依赖的不变量是否可以破坏 只有当你明确回答“不”时,你才能公开一名会员。然而,在这种情况下,你可以问:无论如何,为什么它是这个班的一员 考虑这个简单的例子:
struct foo {
int a,b,sum;
foo(int a,int b) : a(a), b(b), sum(a+b) {}
};
为确保
sum==a+b
始终有效,所有成员都不应为公共成员。另一方面,考虑<代码> STD::配对< /代码>,这只是一个数据结构,所以有<代码>第一个/代码>和<代码>第二个/代码>公共是好的。“<代码> MyA<代码>公用意味着它可以被改变而没有<代码> B/COD>知道它。”因此,核心问题是,<代码> B<代码>需要知道这样的改变。如果是:解决方案似乎显而易见。如果否:这是一个品味和偏好的问题。您可能希望实际提供更好的接口,而不是公开实现细节。如果B
需要控制myA
的值,那么公共变量就错了,错了,错了。一般来说,我建议不要这样做。在某些特定情况下,这可能是有意义的。但总的来说,根据我的经验,对于OOP来说,最好尽可能多地遵守。我认为现在是考虑是否真的需要myA成为B的成员的时候了。备选方案可能是myA是独立对象,B只有一个对它的引用。当然,只有当myA可以对其进行B不需要知道的修改时,这才是可以的。在这里,声明函数const可能有助于提高可读性。也许你需要把A分成两个类,一个在B里面,一个在B外面,这有一个对B类的引用。
struct foo {
int a,b,sum;
foo(int a,int b) : a(a), b(b), sum(a+b) {}
};