The problem here is that alphaName and betaName are member variables. That means they are initialized during the Alpha and Beta constructors. However, the superclass constructor of Parent mustis always be called first, before calling the child class constructors. That means thatResult: Parent::Parent(char *) is called with an uninitialized pointer.
Here is your code on the Compiler Explorer: https://godbolt.org/z/otAuQU
As you can see, Alpha::Alpha() compiles to the following:
call Parent::Parent(char*)
ldd r24,Y+1
ldd r25,Y+2
ldi r18,lo8(.LC0)
ldi r19,hi8(.LC0)
.LC0 is the string "ALPHA".
The solution here is to make the names static. That way, they are initialized before the parent constructor is called.
class Parent {
protected:
const char *const childName;
public:
Parent(const char* childName) : childName(childName) {}
const char *getChildName () const {
return childName;
}
};
class Alpha : public Parent {
protected:
constexpr static const char *alphaName = "ALPHA";
public:
Alpha() : Parent(alphaName) {
Serial.print(F("My name is "));
Serial.println(getChildName());
}
};
This compiles to:
ldi r22,lo8(.LC0)
ldi r23,hi8(.LC0)
call Parent::Parent(char const*)
As others have mentioned, pointers to string literals should always be const. The only reason this doesn't give an error is because the Arduino folks decided that it was a good idea to compile everything with -fpermissive ...
Mutating a string literal is undefined behavior, so an error.