Conversion of pointer-to-pointer between derived and base classes?
Asked Answered
S

2

16

Regarding the following C++ program:

class Base { };

class Child : public Base { };

int main()
{   
    // Normal: using child as base is allowed
    Child *c = new Child();
    Base *b = c;

    // Double pointers: apparently can't use Child** as Base**
    Child **cc = &c;
    Base **bb = cc;

    return 0;
}

GCC produces the following error on the last assignment statement:

error: invalid conversion from ‘Child**’ to ‘Base**’

My question is in two parts:

  1. Why is there no implicit conversion from Child** to Base**?
  2. I can make this example work with a C-style cast or a reinterpret_cast. Using these casts means throwing away all type safety. Is there anything I can add to the class definitions to make these pointers cast implicitly, or at least phrase the conversion in a way that allows me to use static_cast instead?
Solute answered 28/3, 2010 at 9:25 Comment(2)
Variations on this question in many programming languages is one of the most common questions on SO. But everyone phrases it slightly differently even for the same language, so finding duplicates can be difficult.Kamseen
"Fixing" this example to avoid shady casts will depend on why you are using a pointer-to-pointer in the first place.Emotional
M
27

If this was allowed, you could write this:

*bb = new Base;

And c would end up pointing to an instance of Base. Bad.

Massengale answered 28/3, 2010 at 9:30 Comment(5)
Small correction - he could say **bb = new Base(); Just *bb wouldn't be allowed.Fractostratus
@Phil: new returns a pointer, which is type *Base. bb is of type **Base. Thus *bb is the right level of dereference.Lippert
The rationale is essentially the same as the comp.lan.g.c FAQ about the non-equivalence of char** and char const**: c-faq.com/ansi/constmismatch.htmlPreconception
@Dav: sorry, I was assuming you replaced the line Base **bb = cc, with Base **bb = new Base(). Don't know where I got that idea though, since if I thought that, your Base *b = new Base() would be perfectly legal. My mistake!Fractostratus
(bow) Simple and clear, and saved today's logic-bepuzzling-quota for other problems. :)Hamel
M
1

Pointers are virtual address. Normally you are responsible for what you do with it. Using msvc 2019. I can cast one to base, but not two:

example 1:

int p;
int *p1 = &p;
int **p2 = &p1; //OK

example 2:

struct xx {};
struct yy : public xx {};

yy p;
yy *p1 = &p;
xx **p2 = &p1; //Just a strange error

example 3:

struct xx {};
struct yy : public xx {};

yy p;
xx *p1 = &p; 
xx **p2 = &p1; //OK
Margiemargin answered 10/5, 2020 at 8:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.