I would first define your class Person like this instead:
class Person {
int Age;
int ID;
protected:
Person(int age, int id): Age{age}, ID{id} {}
public:
virtual ~Person() = default;
};
That is, Person's constructor is made protected so that a class outside the hierarchy can't create a Person object, and its destructor is made virtual to make it suitable as a base class for a polymorphic type.
Then, both Child and Adult publicly inherit from Person, as you already have them. Their constructors end up calling Person's constructor with the same parametrization their constructors receive:
class Adult: public Person {
public:
Adult(int age, int id): Person(age, id) {}
// ...
};
class Child: public Person {
public:
Child(int age, int id): Person(age, id) {}
// ...
};
Finally, for creating objects that derived from Person, I would create the factory function below:
std::unique_ptr<Person> create_person(int age, int id) {
if (age < 18)
return std::make_unique<Child>(age, id);
else
return std::make_unique<Adult>(age, id);
}
This factory function creates a Child object if the to-create person's age is under 18. Otherwise, it creates an Adult object. This – determining the type of the object to create – is done at run time.
EDIT: You wondered how a Child object could become an Adult object after its age has reached 18 years old.
I would suggest making the state of a Person object immutable so that a fresh new object has to be created every time the age of a person is increased. This way, creating a new object from an existing one will be the only way to grow a Person's age and, at that moment, you will have the control to decide whether to create a Child or Adult object based on the new age.
For doing this, first, qualify the Age data member in Person as const (you can do the same with ID). Then, define the following Person's member function which always creates a new object (with the same ID) resulting from increasing a Person's object Age by one:
std::unique_ptr<Person> Person::increase_age() const {
return create_person(Age + 1, ID);
}
As you see, it delegates the creation of the object to the factory function, create_person(), already explained above. This member function can be called on both Child and Adult objects since it inherits from Person.