Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setters/getters and hierarchical data structures

Tags:

c++

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, e.g. ptr_to_A->d1.d4.d7 and so on... But what's the approach when we use setters/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. 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?

like image 930
jbgs Avatar asked Feb 18 '23 00:02

jbgs


1 Answers

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. 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.

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

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:

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. 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.

like image 67
Joseph Mansfield Avatar answered Feb 19 '23 14:02

Joseph Mansfield