views:

120

answers:

3

Why do I get a compilation error when I call a base-class function with a pointer to a pointer to an inherited class?

Example:

class cFoo {};
class cBar : public cFoo {};
void func1(cFoo *) {}  // base class
void func2(cFoo **) {}  // base class

void main(void)
{   cBar bar, *pbar;   // inherited class

    func1(&bar);   // compiles OK
    func2(&pbar);  // fail
    func2(dynamic_cast<cFoo**>(&pbar));  // 'class cFoo ** ' : invalid target type for dynamic_cast
}

How do I get around this?

+2  A: 

It doesn't work because dynamic_cast works on pointers or references to classes. And you're trying to use it on pointers to pointers.

The simple fix would be something like this:

func2(&dynamic_cast<cFoo*>(pbar));
jalf
Isn't that taking the address of a temporary? Is that really allowed?
Anders Abel
Mark B
+6  A: 

Consider the following:

class cFoo {};
class cBar : public cFoo {};
void func1(cFoo *) {}
void func2(cFoo **p) { *p = new cFoo; }  // modify pointee

void main(void)
{   cBar bar, *pbar;   // inherited class

    func1(&bar);   // compiles OK

    func2(&pbar);
}

If that worked, you would have managed to put a cFoo object into a cBar pointer with no compiler error, and the type system would be subverted. A dynamic cast would not help, since there is no way the cast could prevent the damage.

TomW
A: 

What you are trying to do is flawed.

The typical use case for a (non const) pointer-to-a-pointer as a function argument - is that the function will modify the argument to point to a pointer of some instance.

It is the function that chooses the instance. Example a factory method.

The type of argument describes the type that the function guarantees to be valid.

If your function guaranteed that the instance was a cBar then it should take a cBar** argument.

As it takes a cFoo** it only guarantees that the object is a valid cFoo.

In the current form if you force a cast you will cause any type of cFoo to be exposed as a cBar - even if that is not the case.

morechilli
Yes, I kind of suspected that was the problem. I can't expect func2() to know it's being passed a cBar**. In real life I'm doing exactly what TomW shows above (allocating memory).Sigh... I can work around it, but it won't be as elegant.Thank you all for your prompt and expert help.