我有两个对象A和B。现在,B将A存储为局部类变量。
class B
{
A myA;
}
现在,B有很多方法,它们使用其内部的myA
做一些事情,并且我可以使用这些方法,因为它们是公共的。
但是有时候,我需要使用myA
本身。所以我要做的就是将其公开,然后我可以写myB.myA.someMethodFromA()
。
这还好吗,还是风格不好?我的意思是,我知道我可以通过B类中的方法提供对myA
的间接访问器,但是当我可以直接访问myA
时,这似乎是不必要的。
例如,如果myA
拥有方法doStuffviaA
,我宁愿说myB.myA.doStuffViaA()
,而不必先在B中写一个方法说
void doStuffViaB() { myA.doStuffViaB() }
但是,当然,myA
公开意味着它可以在B
不知道的情况下进行更改。该怎么办?
答案 0 :(得分:3)
是的,使其成为public
可以避免封装,并且代码会不断蔓延,从而使您的对象进入不确定的状态。
半途而废的选择是供应
const A& getMyA() const
{
return myA;
}
从那时起,如果至少使用const
个功能,则只能在myA
成员上执行此功能。我当然希望doStuffViaA
是 const
,然后您会写
myB.getMyA().someMethodFromA();
答案 1 :(得分:2)
该怎么办?
这取决于并且实际上非常取决于特定的方案。通常,我建议您
如果无法使用后者(例如,由于“设计约束”或对“便利”的强烈渴望),则可以提供@Bathsheba's answer中发布的吸气剂。另外,您可以将指向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;
};
请注意,这需要C ++ 17。给定成员函数A::doStuff(int)
,可以使用
B b;
b.invokeOnA(&A::doStuff, 42);
b.invokeOnA([](A& a){ a.doStuff(42); });
可以通过另一种间接方式解决该问题,而无需使用getter方法。但是请注意,该方法在质量上与提供一种getter方法非常相似,即拥有精美的功能模板并不能使您摆脱在特定用例中必须打破封装的理由。
答案 2 :(得分:0)
我认为您已经达到了关键点:
但是,当然,将myA公开意味着无需更改即可 B知道了。该怎么办?
使成员成为公共或私人成员不只是为了方便。问问自己:如果成员是公开的,我的班级依赖的不变式会否打破?
仅当您可以肯定地以“否”回答时,您才能将成员公开。但是,在这种情况下,您可能会问:为什么仍然是该类的成员?
考虑这个简单的示例:
struct foo {
int a,b,sum;
foo(int a,int b) : a(a), b(b), sum(a+b) {}
};
为确保sum == a+b
始终有效,所有成员都不应该公开。另一方面,请考虑std::pair
,它只是一种数据结构,因此可以公开使用first
和second
。