It seems to me that you are misinterpreting something, or at least the way you implement this is very weird. It seems as if you want to have Harry
and Jame
as instances of Child
and not actually a derived class of Child
. The reason why I say this is, because Harry
and Jame
do not seem to be designed as classes, but as interfaces to controlling one instance of a single class. A better way of handling this is that when you define Child
you could do it like:
class Child{
private:
bool canSleep;
bool canSit;
std::string name;
public:
Child(std::string _name,bool sleep, bool sit)
: name(_name), canSleep(sleep), canSit(sit) {}
void sit(){
if(canSit) std::cout << name << " can sit\n";
}
void sleep(){
if(canSleep) std::cout << name << " can sleep\n";
}
};
You could also extend this with enum
s implementing flags instead of booleans, but that just helps with usability.
As for the actual question and one solution (and some issues with the code):
There is no syntax (as far as I'm aware) that would allow you to do this, the way presented here, but you can use templates. If you can use C++20 you can even constrain it easily so bad calls are caught compile time, and also produce way less noise. You can make AddChild
into a template like:
// Only for c++20
#include <concepts>
class Parent {
private:
std::vector<Child*> children;
public:
template<typename Child_type>
requires std::derived_from<Child_type,Child> // Only for C++20
void addChild(std::string name){
children.push_back(new Child_type(name));
}
};
Now this is a very basic solution and can be called by parent.addChild<Harry>("Harry");
for example.
There are however other issues that I somewhat tried to mitigate. Firstly in a class every member you declare is private
by default, meaning that no one outside the class (apart from friend
functions, which would be a really hacky solution in this case), can access those members (including functions).
You also can't really store Harry
, where a Child
should go. You can store a pointer to Harry
where a pointer to a Child
should go however. I used raw pointers (which you should generally avoid), but you should look up std::unique_ptr
and std::shared_ptr
, as raw pointers are a pain.
You would also need to define sit
and sleep
as virtual
functions to be able to reference them from a pointer to a Child
(without casting to the derived types, which can be problematic if not done properly (edit: see other answer for doing it properly with dynamic_cast
)).
Finally it seems you are using using namespace std;
, so obligatory: It's bad practice and can lead to very difficult to debug issues.