简体   繁体   English

Setter / getters和分层数据结构

[英]Setters/getters and hierarchical data structures

I know it is considered a bad idea to have public fields in your class. 我知道在你班上有公共领域被认为是个坏主意。 But what's the best approach when your class includes numerous hierarchical data structures and fields? 但是,当您的类包含众多分层数据结构和字段时,最好的方法是什么? For example: 例如:

class A {B d1; C d2; D d3;}
class B {E d4; F d5;}
class E {G d6; int d7;}

In C it is quite easy to access such a data structure, eg ptr_to_A->d1.d4.d7 and so on... But what's the approach when we use setters/getters? 在C中,访问这样的数据结构非常容易,例如ptr_to_A-> d1.d4.d7等等......但是当我们使用setter / getters时,方法是什么?

When using setters and getters in C++, expressions like A.get_d1().get_d4().get_d7() don't seem convenient, and they force returning references. 在C ++中使用setter和getter时,像A.get_d1()。get_d4()。get_d7()这样的表达式似乎不方便,它们强制返回引用。 Since some structures are pretty big, returning by value seems a terrible idea. 由于某些结构非常大,按价值返回似乎是个糟糕的主意。

Which approach or coding style do you use in these cases? 在这些情况下,您使用哪种方法或编码方式? Maybe getting rid of setters/getters and making these fields public? 也许摆脱setter / getters并将这些领域公之于众?

In my coding style, a class should not expose public "raw" data members, but only getters and setters (even if they are simple one-line methods). 在我的编码风格中,类不应该暴露公共“原始”数据成员,而应该只暴露getter和setter(即使它们是简单的单行方法)。

This is because the code can be upgraded in the future, and the single-line method can be expanded to something more complicated (or some debug-only builds features can be added to check some invariants, etc.), so it's better to keep the interface consistent for the clients (which is not possible if you expose "raw" data members). 这是因为代码可以在将来升级,并且单行方法可以扩展到更复杂的东西(或者可以添加一些仅调试构建功能来检查一些不变量等),所以最好保持客户端的接口一致(如果您公开“原始”数据成员,这是不可能的)。

You can avoid using the get_() prefix, and just consider the data member as a "property" with a simple (without get_... ) name, eg 您可以避免使用get_()前缀,只需将数据成员视为具有简单(不带get_... )名称的“属性”,例如

class Shape
{
public:
  ....

  COLORREF Color() const // Just Color() i.e. the property name, without get_...
  {
     return m_color;
  }

private:
  COLORREF m_color;
};

And write client code like: 并编写客户端代码,如:

Shape s;
COLORREF someColor = s.Color();

which looks fine to me. 这对我来说很好看。

For the setter you can use a syntax like: 对于setter,您可以使用如下语法:

Shape& Color(COLORREF color)
{
    m_color = color;
    return *this;
}

and write client code like: 并编写客户端代码,如:

Shape s;
s.Color(...).Draw(); // set color and draw shape

If the type of the property is something more complex than a COLORREF (which is a 32-bit DWORD ), you can use a pattern like: 如果属性的类型比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;
}

I know it is considered a bad idea to have public fields in your class. 我知道在你班上有公共领域被认为是个坏主意。

This is a sweeping statement that has come from last decade's Java development. 这是来自上一个十年Java开发的全面声明。 You should be considering whether a member should be public or private on a member-by-member basis. 您应该考虑成员应该是逐个成员公开还是私有。 There are times when a public data member is the right idea. 有时公共数据成员是正确的想法。 Consider the following questions: 请考虑以下问题:

  1. Do I need to maintain an invariant over this member? 我是否需要对此会员保持不变?
  2. Can this member have an invalid value? 该成员可以使用无效值吗?
  3. Do I want the interface to give an alternate representation of this member? 我是否希望界面为该成员提供替代表示?

If the answer to any of the above questions is yes, you probably want to use a getter. 如果上述任何问题的答案都是肯定的,那么您可能想要使用一个getter。

Also consider whether it actually makes sense to set members individually. 还要考虑单独设置成员是否真的有意义。 Perhaps you should be setting members with the constructor, and you want to provide some other interface that modifies those members. 也许您应该使用构造函数设置成员,并且您希望提供一些修改这些成员的其他接口。

When using setters and getters in C++, expressions like A.get_d1().get_d4().get_d7() don't seem convenient 在C ++中使用setter和getter时,像A.get_d1()。get_d4()。get_d7()这样的表达式似乎不方便

While it's not too uncommon to have fairly deep nesting of data structures, usually a specific piece of code shouldn't have to delve too far into it. 虽然对数据结构进行相当深的嵌套并不常见,但通常一段特定的代码不应该深入研究它。 If it does, I imagine it's probably doing more than it should, going beyond its single responsibility. 如果确实如此,我想它可能做得比它应该做的更多,超出了它的单一责任。 However, if it is a common task to get d7 from an A object, perhaps A should expose it in its interface: 但是,如果它是一个共同的任务,以获得d7A对象,也许A应该暴露在其界面:

int A::get_d7 {
  return get_d1().get_d4().get_d7();
}

Since some structures are pretty big, returning by value seems a terrible idea. 由于某些结构非常大,按价值返回似乎是个糟糕的主意。

Actually, with modern C++, this is not a problem at all. 实际上,使用现代C ++,这根本不是问题。 Passing by value should be considered your default mode of object passing. 传递值应该被视为对象传递的默认模式。 This is because temporary objects can now be moved from, which is essentially a very efficient form of copying. 这是因为现在可以移动临时对象,这实际上是一种非常有效的复制形式。

If you are just using a class as a pure data structure, and there is no behavior relating to that data that you want to encapsulate, then use a struct instead and access the fields directly. 如果您只是将类用作纯数据结构,并且没有与要封装的数据相关的行为 ,则使用struct代替直接访问字段。 Bjarne Stroustrup recommends this approach . Bjarne Stroustrup推荐这种方法 This is equivalent to using a class and declaring all the members as public , but calling it a struct instead makes it clearer that it is nothing more than simple collection of data. 这相当于使用一个class并将所有成员声明为public ,但将其称为struct则更清楚地表明它只不过是简单的数据集合。

If you are doing more than just storing data, then use getters and setters. 如果您所做的不仅仅是存储数据,那么请使用getter和setter。

When using setters and getters in C++, expressions like A.get_d1().get_d4().get_d7() don't seem convenient, and they force returning references. 在C ++中使用setter和getter时,像A.get_d1()。get_d4()。get_d7()这样的表达式似乎不方便,它们强制返回引用。 Since some structures are pretty big, returning by value seems a terrible idea. 由于某些结构非常大,按价值返回似乎是个糟糕的主意。

No, you can choose whether to return by reference or by value. 不,您可以选择是通过引用还是按值返回。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM