There is no need to use new here. Usage of new should be limited to low-level code only.
C++ Core Guidelines R.11: Avoid calling new and delete explicitly
The Leg and Body classes also violate the rule of 3/5/0 and will corrupt memory:
C++ Core Guidelines C.21: If you define or =delete any copy, move, or destructor function, define or =delete them all
If you ever (explicitly or implicitly) make a copy of a Leg, for example, you're in for a bad time:
Leg l1(0, 1, 2);
Leg l2 = l1;
==1==ERROR: AddressSanitizer: attempting double-free on 0x6020000000d0 in thread T0:
#0 0x7f83f4d72dd7 in operator delete(void*, unsigned long) (/opt/compiler-explorer/gcc-11.2.0/lib64/libasan.so.6+0xb3dd7)
#1 0x401b05 in Leg::~Leg() /app/example.cpp:48
#2 0x4015c4 in main /app/example.cpp:111
#3 0x7f83f47760b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
#4 0x4011fd in _start (/app/output.s+0x4011fd)
Avoid all these issues by just using “the rule of zero” (i.e. not doing any resource management in custom destructors at all):
const uint8_t NUM_LEGS = 2;
class Joint {
public:
int number;
Joint(int number) : number(number) {
Serial.print("Joint::Joint("); Serial.print(number); Serial.println(")");
}
~Joint() {
Serial.print("Joint::~Joint("); Serial.print(number); Serial.println(")");
}
void begin() {
Serial.print("Joint::begin("); Serial.print(number); Serial.println(")");
}
};
class Leg {
private:
Joint joint1;
Joint joint2;
Joint joint3;
public:
Leg(Joint joint1, Joint joint2, Joint joint3)
: joint1(joint1), joint2(joint2), joint3(joint3) {
Serial.print("Leg::Leg(");
Serial.print(joint1.number); Serial.print(", ");
Serial.print(joint2.number); Serial.print(", ");
Serial.print(joint3.number); Serial.println(")");
}
void begin() {
joint1.begin();
joint2.begin();
joint3.begin();
}
void nextStep() {
Serial.print("Leg::nextStep(");
Serial.print(joint1.number); Serial.print(", ");
Serial.print(joint2.number); Serial.print(", ");
Serial.print(joint3.number); Serial.println(")");
}
};
class Body {
public:
Leg legs[NUM_LEGS] {
{0, 1, 2},
{3, 4, 5},
};
void begin() {
for (Leg &l : legs)
l.begin();
}
void nextStep() {
for (Leg &l : legs)
l.nextStep();
}
};
void setup() {
Serial.begin(115200);
Serial.println("Creating Body");
Body body;
body.begin();
body.nextStep();
// here Body gets deleted as it's local to the function so you'll see messages from the destructors
Serial.println("Deleting Body");
}
void loop() {}