views:

388

answers:

5

Is it possible to getting rid of error C2243?

class B {};
class D : protected B {};

D d;
B *p = &d;   // conversion from 'D *' to 'B &' exists, but is inaccessible

I had this error in my app and at the end I've managed to compile it by making an explicit conversion:

D d;
B *p = (B*)&d;

I can't understand why by making class D inherited protected from B makes the implicit conversion inaccessible.

I tried to avoid explicit conversion by creating a operator B() in class D in order to make the conversion accessible:

class B {};
class D : protected B 
{
 public:
 operator B() {return *this;}
};

But there is no way.

Any other solution to avoid explicit conversion?

+4  A: 

Because protected and private inheritance are not is-a relationship, they are just syntax sugar for composition. Your classes can be rewritten exactly like this, but you lose the convenience of letting the compiler define b for you, and using b members directly instead of referring to it explicitly :

class D
{
  protected:
  B b;
};


For the second point of your question:

operator B() {return *this;}

This line has to do with B and D. D* and B* are totally different from B and D though they are pointers to them! to cast pointers, you could reinterpret the pointer:

B *p = reinterpret_cast<B*>(&d); // TOTALLY WRONG, although it compiles :)

Don't do the above line! I think you might give us more info of what you are trying to achieve.

AraK
+7  A: 

If you want to allow conversion, you should be using public inheritance.

Using protected or private inheritance, you are declaring that the fact that the derived type inherits from the base class is a detail that should not be visible from the outside: that's why you are getting that error.

You should regard non-public inheritance only as a form of composition with the added possibility to override methods.

Paolo Tedesco
+1  A: 

Because out of D and Ds children, nobody knows that they are parent-child, so you need to do it explicitly.

Thats what protected inheritance means, only your family(children) will know that you inherit. And you could use it, for example in a children method, there an implicit conversion would be legal.

If you want to have implicit conversion out of your children you need to make it public for everyone to know.

Arkaitz Jimenez
A: 

Did you try making operator B() public in class D? In the code you showed, it would be marked protected and still inaccessible. But I would avoid conversion operators in general if possible.

Still, inheriting protected B means you intend to prevent doing B* p = &d. Imagine if B was actually a protected member variable at the top of D. Just like you can't access D.b in that case, you can't access d as a B*, unless you cast it away.

So either inherit B publically, or use your casts. I'd go with inheriting B publically, because inheriting it protected basically says "Don't use me as a B", which you are trying to do anyway.

AshleysBrain
making operator B() public doesn't work either
lucas29252
+1  A: 

The problem here is that you are trying to do an end run around the information hiding that the protected attribute provides. If you want to access an instance of D as a B, why have you inherited it as protected rather than public?. What you are saying in using protected inheritance is that you wish only instances of D and its descendants to be aware of the B component. You need to look again at what you want to accomplish.

The old C style cast that you are using has none of the subtlety of the newer C++ casts so it gives you code that will compile but the problem is really in the inheritance.

Dr. Tim