How to initialize and array of objects in constructor?

Hello,
I have a class that works fine on it’s own (WidgetI2C), and I can create an array of these objects in a sketch. Next I need to create a new class that contains an array of these objects. I know that in Arduino it’s not possible to create instances in the constructor and you are required to use an initializer list in the constructor. Here is an example of what I’m trying to do:

header:

#ifndef WidgetArray_h
#define WidgetArray_h
#include <wire.h>
#include "Arduino.h"
#include "WidgetI2C.h"
#define byte uint8_t

class WidgetArray{
public:
  Widgetarray(				                              //constructor
    byte add0, float x0, float y0, float z0,        //1st Widget with I2C address and (X,Y,Z) coordinates (cm)
    byte add1, float x1, float y1, float z1,        //2nd Widget with I2C address and (X,Y,Z) coordinates (cm)
    byte add2, float x2, float y2, float z2);       //3rd Widget with I2C address and (X,Y,Z) coordinates (cm)
  
  WidgetI2C arW[3];
  
};
#endif

Here’s the implementation:

#include "Arduino.h"
#include "WidgetArray.h"
#include "WidgetI2C.h"

#define uint8_t byte

WidgetArray::WidgetArray(			            //constructor
    byte add0, float x0, float y0, float z0,        //1st Widget with I2C address and (X,Y,Z) coordinates (cm)
    byte add1, float x1, float y1, float z1,        //2nd Widget with I2C address and (X,Y,Z) coordinates (cm)
    byte add2, float x2, float y2, float z2):       //3rd Widget with I2C address and (X,Y,Z) coordinates (cm)
    arW();
      
  arW[0] = WidgetI2C(add0);
  arW[1] = WidgetI2C(add1);
  arW[2] = WidgetI2C(add2);
}

I’ve tried many different ways, but usually get the error:
error: no matching function for call to 'WidgetI2C::WidgetI2C()

If I try to instantiate the WidgetI2C’s in the initializer list, I get the error:
error: bad array initializer

Thanks,
Kevin

I've tried many different ways

What errors does this way produce? What does WidgetI2C.h look like?

Here’s all 5 files. Use this set for consistency:

arWidget.ino

#include "WidgetI2C.h"
#include "WidgetArray.h"

void setup(){};
void loop(){};

WidgetArray.cpp

#include "Arduino.h"
#include "WidgetArray.h"
#include "WidgetI2C.h"

#define byte uint8_t

WidgetArray::WidgetArray(			    //constructor
    byte add0, float x0, float y0, float z0,        //1st Widget with I2C address and (X,Y,Z) coordinates (cm)
    byte add1, float x1, float y1, float z1,        //2nd Widget with I2C address and (X,Y,Z) coordinates (cm)
    byte add2, float x2, float y2, float z2):       //3rd Widget with I2C address and (X,Y,Z) coordinates (cm)
    arW();
      
  arW[0] = WidgetI2C(add0);
  arW[1] = WidgetI2C(add1);
  arW[2] = WidgetI2C(add2);
}

WidgetArray.h

#ifndef WidgetArray_h
#define WidgetArray_h
#include <wire.h>
#include "Arduino.h"
#include "WidgetI2C.h"
#define byte uint8_t

class WidgetArray{
public:
  WidgetArray(				                              //constructor
    byte add0, float x0, float y0, float z0,        //1st Widget with I2C address and (X,Y,Z) coordinates (cm)
    byte add1, float x1, float y1, float z1,        //2nd Widget with I2C address and (X,Y,Z) coordinates (cm)
    byte add2, float x2, float y2, float z2);       //3rd Widget with I2C address and (X,Y,Z) coordinates (cm)
  
  WidgetI2C arW[3];
  
};
#endif

WidgetI2C.cpp

#include "Arduino.h"
#include "WidgetI2C.h"
#define byte uint8_t

WidgetI2C::WidgetI2C(byte add){
	address = add;
}

WidgetI2C.h

#ifndef WidgetI2C_h
#define WidgetI2C_h
#include "Arduino.h"
#define byte uint8_t

class WidgetI2C{
	WidgetI2C(byte add);
	
	byte address;
};
#endif

The full error message is:
WidgetArray.cpp:11: error: no matching function for call to ‘WidgetI2C::WidgetI2C()’

Thanks!

Your WidgetI2C class does not have a no-argument constructor. Therefore, you can't declare an array of them the way you are.

You have two choices. One would be to create an array of pointers, instead, and the create the instances in the WidgetArray constructor, and point to them.

The other is to create a no-argument constructor for WidgetI2C, and add a method that sets the value that the one-argument constructor sets.

Hi Paul,
Is there no way to initialize the arW in the constructor, something like this:

WidgetArray::WidgetArray(			    //constructor
    byte add0, float x0, float y0, float z0,        //1st Widget with I2C address and (X,Y,Z) coordinates (cm)
    byte add1, float x1, float y1, float z1,        //2nd Widget with I2C address and (X,Y,Z) coordinates (cm)
    byte add2, float x2, float y2, float z2):       //3rd Widget with I2C address and (X,Y,Z) coordinates (cm)
    arW({WidgetI2C(add0), WidgetI2C(add1), WidgetI2C(add2)});
     
}

or

WidgetArray::WidgetArray(			    //constructor
    byte add0, float x0, float y0, float z0,        //1st Widget with I2C address and (X,Y,Z) coordinates (cm)
    byte add1, float x1, float y1, float z1,        //2nd Widget with I2C address and (X,Y,Z) coordinates (cm)
    byte add2, float x2, float y2, float z2):       //3rd Widget with I2C address and (X,Y,Z) coordinates (cm)
    arW() ={WidgetI2C(add0), WidgetI2C(add1), WidgetI2C(add2)};
     
}

Thanks!
Kevin

The problem is not one of initializing the array. You have to declare the array in one file, and initialize it in another. When you declare an array of objects, the objects are constructed. That requires a no argument constructor.

Outside of a class, you can declare and initialize an array of objects whose constructors take arguments. In a class, you can not.

Pointers or define a no argument constructor are your choices.

Thanks for clearing that up Paul. I went with the no argument constructor and it's working fine.

Thanks again!
Kevin