我知道在你的课堂上设置公共字段被认为是一个坏主意。但是,当您的类包含众多分层数据结构和字段时,最好的方法是什么?例如:
class A {B d1; C d2; D d3;}
class B {E d4; F d5;}
class E {G d6; int d7;}
在C中,很容易访问这样的数据结构,例如ptr_to_A-> d1.d4.d7等等......但是当我们使用setter / getters时的方法是什么?
在C ++中使用setter和getter时,像A.get_d1()。get_d4()。get_d7()这样的表达式似乎不方便,它们会强制返回引用。由于某些结构非常大,按价值返回似乎是一个糟糕的主意。
在这些情况下,您使用哪种方法或编码方式?也许摆脱setter / getters并将这些领域公之于众?
答案 0 :(得分:2)
在我的编码风格中,一个类不应该暴露公共的“原始”数据成员,而应该只暴露getter和setter(即使它们是简单的单行方法)。
这是因为代码可以在将来升级,并且单行方法可以扩展到更复杂的东西(或者可以添加一些仅调试构建功能来检查一些不变量等),所以它是更好地保持客户端的接口一致(如果您公开“原始”数据成员,这是不可能的。)
您可以避免使用get_()
前缀,只需将数据成员视为具有简单(不含get_...
)名称的“属性”,例如
class Shape
{
public:
....
COLORREF Color() const // Just Color() i.e. the property name, without get_...
{
return m_color;
}
private:
COLORREF m_color;
};
编写客户端代码,如:
Shape s;
COLORREF someColor = s.Color();
对我来说很好看。
对于setter,您可以使用如下语法:
Shape& Color(COLORREF color)
{
m_color = color;
return *this;
}
并编写客户端代码,如:
Shape s;
s.Color(...).Draw(); // set color and draw shape
如果属性的类型比COLORREF
(32位DWORD
)更复杂,则可以使用如下模式:
std::wstring Name() const // getter
{
return m_name;
}
Shape& Name(std::wstring name) // setter
{
// Pass by value and move from the value (C++11 move semantics)
m_name = std::move(name);
return *this;
}
答案 1 :(得分:2)
我知道在你的课堂上设置公共字段是一个坏主意。
这是来自上一个十年Java开发的全面声明。您应该考虑成员应该是逐个成员公开还是私有。有时公共数据成员是正确的想法。请考虑以下问题:
如果上述任何问题的答案都是肯定的,那么您可能想要使用吸气剂。
还要考虑单独设置成员是否真的有意义。也许您应该使用构造函数设置成员,并且您希望提供一些修改这些成员的其他接口。
在C ++中使用setter和getter时,像A.get_d1()。get_d4()。get_d7()这样的表达式似乎不方便
虽然对数据结构进行相当深的嵌套并不常见,但通常一段特定的代码不应该深入研究它。如果确实如此,我想它可能做得比它应该做的更多,超出了它的单一责任。但是,如果从d7
对象获取A
是一项常见任务,则A
可能应在其界面中公开它:
int A::get_d7 {
return get_d1().get_d4().get_d7();
}
由于某些结构非常大,按价值返回似乎是一个糟糕的主意。
实际上,使用现代C ++,这根本不是问题。传递值应该被视为对象传递的默认模式。这是因为现在可以移动临时对象,这实际上是一种非常有效的复制形式。
答案 2 :(得分:1)
如果您只是将一个类用作纯数据结构,并且没有与要封装的数据相关的行为,那么请改用struct
并访问直接领域。 Bjarne Stroustrup recommends this approach。这相当于使用class
并将所有成员声明为public
,但将其称为struct
则更清楚地表明它只不过是简单的数据集合。
如果您所做的不仅仅是存储数据,那么请使用getter和setter。
在C ++中使用setter和getter时,表达式如 A.get_d1()。get_d4()。get_d7()似乎不方便,而且他们强迫 返回参考。由于一些结构非常大,所以返回 按价值似乎是一个可怕的想法。
不,您可以选择是按引用还是按值返回。