Best practice when initialising class variables

#include <Arduino.h>
class foo {
  public:
    int bar1 = 0;
    int bar2 = 0;
    int bar3 = 0;

    foo(int foo1,int foo2,int foo3) //all variables initialised during creation
    {
      bar1=foo1;
      bar2=foo2;
      bar3=foo3;
    };
    void beginFoo(int foo1,int foo2,int foo3) //all variables initialised in setup()
{
      bar1=foo1;
      bar2=foo2;
      bar3=foo3;
};
    void setBar1(int param1)// set methods to setup variables
    {
      bar1 = param1;
    };
};

foo foobar(1, 2, 3);//instantiate object

void setup() {
  //foobar.beginFoo(5, 6, 7);
}

void loop() {
  Serial.begin(9600);
  delay(1000);
  foobar.setBar1(4);
  Serial.println(foobar.bar1);
  Serial.println(foobar.bar2);
  Serial.println(foobar.bar3);
  while (1)
  {
    delay(100);
  }
}

The above is for a hook for discussion. I will have a class which has many public parameters - its for plotting a graph so there are quite a few natural things that need to be set like colours, axes limits, enables for tick marks, etc. I've done my best to divide out things into sub structures (like axes), but the main graph object still has a fair number of parameters.

My question is: when the parameter list is long, what's the best practice for initialising a class instance?

Above there are variables defined in the constructor; variables defined in an initialiser; and set methods for each variable (OK I only put one in). It seems to me that set methods are cumbersome and produce a lot of code waffle, but the other options mean that all parameters must be defined together resulting in inefficiency. Is there a middle ground?

Then the other thing is the naming of parameters. Internally the variables of the class have one name and in the method definitions they have another name - is this always necessary - do you have to have two names for everything, in essence?

Please excuse my lack of OO experience - I'm trying to learn how to do it properly :slight_smile:
I was brought up on assembler and BASIC, with a splash of Algol ..

For a complex object like that it's probably a combination - set the critical parameters in the constructor and provide setter/getter functions to allow control of the others.

Begin functions are usually used when the object touches hardware that should be initialized before the object is used. Constructors run before init, so you need something you can call later.

I miss the most flexible way (useful for references or constants)

    foo(int foo1,int foo2,int foo3) : bar1{foo1}, bar2{foo2}, bar3{foo3} {};

I would never initialize that way, but maybe that's a matter of taste.

Apart from it being an example - (you might well have int bar[3], ofc. )

What's your way and why?

Also, usually, local variables would not be public in a situation where you're accessing them through object functions.

If I understand you correctly:

either use set method:

obj.setvar(value);

or

obj.var=value;

not both. And for the later public and the prior private?

And then there is the virtual insanity with C++ constructors; A derived class will not execute the constructor of its base class unless explicitly told to. Using the initializer list is AFAIR the only way of doing this, so I would opt for using the initializer list for member initialization and put any init code inside the curlies.

Yes. But for OO reasons, you would usually prefer not to grant direct access to a local variable.

You can also use the constructor with default parameters

Foo (int bar1 = 0, int bar2 = 0, int bar3 = 0)
{
}

then to use one of the options

Foo s1 (1, 2, 3);
Foo s2 (1, 2); // bar3 = 0
Foo s3 (1);    // bar2 and bar3 = 0
Foo s4 ();     //all params = 0

In terms of having different names like:

bar1=foo1;

you could either use 'this' to differentiate them in the constructor so:

foo(int bar1, int bar2, int bar3)
    {
this->bar1=bar1;
this->bar2=bar2;
this->bar3=bar3;
};

Or another convention is to use 'm_' for member variables so:

foo(int bar1, int bar2, int bar3)
    {
m_bar1=bar1;
m_bar2=bar2;
m_bar3=bar3;
};

Personal preferences though! I like to do:

foo(int bar1, int bar2, int bar3)
: bar1(bar1), bar2(bar2), bar3(bar3)
    {};

In terms of getters/setters, I don't see the point of writing a setBar1() function if you're only going to call it once to initialise it.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.