0

I have 2 classes: Parent and Child.

class Child : public Parent {...};

I define a variable

vector<Parent*> v;

v has a couple of pointer instances of Child class.

I have a function:

void myFunc(Child *c) {...}

When I call myFunc(v[1]), I get the following error:

Argument of type "Parent*" is incompatible with parameter of type `Child*`.

I thought that the inheritance should work here without a problem, but it doesn't. Could anyone help?

Dima Dz
  • 512
  • 1
  • 5
  • 17
  • 3
    You thought wrong, it works without problem the other way around. – Slava Feb 26 '19 at 18:37
  • 3
    Public inheritance in C++ expresses 'IS-A' principle, where every child is a parent. But it doesn't work the other way around, i.e. a parent is not a child! – SergeyA Feb 26 '19 at 18:39
  • [Wiki page on the is-a relationship.](https://en.wikipedia.org/wiki/Is-a) Unrelated to your problem here but important in general is the Liskov Substitution Principle. I strongly recommend reading the section on it as well. – user4581301 Feb 26 '19 at 18:42
  • There must be a dup somewhere but cannot find a good one – Slava Feb 26 '19 at 18:43
  • @Slava, that's the problem, I didn't find any dups :-) – Dima Dz Feb 26 '19 at 18:44

2 Answers2

2

You have it backwards! The problem being that in C++, the parent-child relationship is one way. Or in other words it's an IS-A relationship.

Basically this means that while children classes can take place of parents, i.e. you can pass a sedan to an automobile vector, you can't go backwards. Because not every automobile is a sedan.

Your function definition should be void myFunc(Child *c) {...} if you ONLY want to take the child class, but if you want to take ANY child of the parent, or the parent itself, then do it like: void myFunc(Parent *p) {...} instead.

Also as a small sidenote, I suggest using references instead of pointers whenever possible. See here for more discussion.

Addendum:

I want to use function overloading to define different behaviour for different types of Childs for myFunc. Any Idea how I can do this?

In order to accomplish this you can use templates and use specialization like so:

#include <iostream>

class automobile {

};

class sedan : public automobile {

};

template <typename T> 
void foo(T& t) { 
  std::cout << "An automobile!" << std::endl;
}

template <> 
void foo<sedan>(sedan& t) { 
  std::cout << "A sedan!" << std::endl;
}

int main() {
  automobile a;
  sedan s;
  foo<automobile>(a);
  foo<sedan>(s);
}

And the output as expected is:

An automobile!
A sedan!
Rietty
  • 1,116
  • 9
  • 24
  • I want to use function overloading to define different behaviour for different types of `Child`s for `myFunc`. Any Idea how I can do this? – Dima Dz Feb 26 '19 at 18:48
  • 1
    You have an IS-A relationship with a sedan. You are a sedan. – Hatted Rooster Feb 26 '19 at 18:54
  • @DimaDz If I understood the question correctly, I edited the answer to show how you can do that with templates – Rietty Feb 26 '19 at 18:55
  • @DimaDz updated code to be more indicative of question – Rietty Feb 26 '19 at 19:06
  • 1
    @DimaDz Alternative to templates: If each child has different behaviour, take advantage of polymporphism and build the function into the classes with a `virtual` method. Example: https://ideone.com/s7AAYW – user4581301 Feb 26 '19 at 19:21
0

In OOP, child class have "is a" relationship with his parent, but the opposite is false. It's logical , for example parent class is human and child class is men , we can say men is human , but human is men it's not true.

nissim abehcera
  • 821
  • 6
  • 7