Pavel Oganesyan
Pavel Oganesyan

Reputation: 6924

Pointer to inherited class instance as function parameter

Here is the problem — I have two classes like this:

class A
{
  //some fields and methods 
   void niceMethod();
};

class B : public A
{
   void niceMethod();
};

class C : public A
{
   void niceMethod();
};

and function

void myFunc(A** arrayOfABC);

//Double * is to notice that I am going to modify the argument.

And I want to do:

(*arrayOfABC)[i].niceMethod();

in my function, getting different things done when I pass array of Bs or Cs to function.

But then I try to call it like

 B* bees = NULL;
    myFunc(&bees);

I have "Argument type of B** is incompatible with parameter of type A**".

I know that I can pass B or C as A to functions like f(A), but what's wrong with pointers?

Upvotes: 2

Views: 513

Answers (2)

n. m. could be an AI
n. m. could be an AI

Reputation: 119877

You can convert B* to A*, but not B** to A**.

Suppose A is fruit and B is apple, then A* is a little arrow that can point to a fruit (any fruit) and B* is a little arrow that can point to an apple (and only an apple). You can take an apple arrow, relabel it as a fruit arrow, and give it to somebody that expects fruit arrows. It indeed points to a fruit because an apple is a kind of a fruit. So far so good, no surprises here.

Now A** is a little arrow that can point to a little arrow that can point to a fruit (any fruit), and B** is a little arrow that can point to a little arrow that can point to an apple (and only an apple). What will happen if you take the latter, and give it to somebody who expects the former? That person can go along the arrow that can point to an arrow that can point to a fruit (any fruit!), take that second arrow, and turn it around and make it point to a banana.

Now the unfortunate apple guy guy who used to have a double-apple-arrow goes along the first arrow, then goes along the second arrow that ought to point to an apple, and finds a banana there, a fruit he sees the first time in his miserable life. That's a pretty unfortunate situation if you ask me. We shouldn't be surprised if things go bananas from this point on!

Upvotes: 2

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726539

The compiler is right, it is indeed incompatible. Consider this:

B* bees = new B[2];
myFunc(&bees); // Imagine that it's allowed

Now inside myFunc you do this:

void myFunc(A** arrayOfABC) {
    // This is OK:
    arrayOfABC[0] = new C();
}

This should be allowed, because C extends A. However, upon return from myFunc your bees would contain a C, which is not good.

To fix this, create an array of A*, and populate it with pointers to B.

P.S. Don't forget to make niceMethod virtual, otherwise it's not going to work the way you expect.

Upvotes: 3

Related Questions