Mr. Ree
Mr. Ree

Reputation: 881

type conversion between inherited classes when passing an argument in C++

The picture below shows three independent tests for this problem :

( I just focus on the declarations but not the definitions of the functions ~~ )

https://i.sstatic.net/wYtA6.png

I wonder why the right one got an error of " 'A' is an inaccessible base of 'B' " .

Why does the g++ seem to initialize the reference to the base by derived class ( which cause the error due to the protected inheritance ) ,

rather than use conversion operator like the middle one to convert B to A and pass in ( which is 0 error and 0 warning ) ?

here is the code of the right one in the picture :

struct A {
    A &operator=( const A & ) { return *this;  }
}a;

struct B : protected A {
    operator A() {  return A();  };
}b;

int main( void )
{
    a = b;
    return 0;
}

Thanks for your help !~

Upvotes: 3

Views: 886

Answers (2)

Sarfaraz Nawaz
Sarfaraz Nawaz

Reputation: 361522

When you write a = b; in the main() or outside the class (in the world), then the conversion happens there, not inside the class, and the accessibility rules apply at the point of conversion (which is outside the class). For such conversion to take place, the base class needs to be accessible from outside (the world).

In your case, since B is derived from A using protected keyword, which means the world cannot access A subobject of b, because of which it cannot convert B into A. It all happens because the base of B (which is A) is inaccessible from the world due to protected inheritance. Make it public, the conversion will happen in the world as well.

Now, this question:

Why isn't the user-conversion-function used instead of inheritance-conversion?

Since inheritance-conversion is preferred over user-defined conversion function, you can think of this preference as the first step, and the second step to be the rule of accessibility, where the conversion fails!

Upvotes: 4

aschepler
aschepler

Reputation: 72401

Section 12.3.2:

A conversion function is never used to convert a (possibly cv-qualified) object to the (possibly cv-qualified) same object type (or a reference to it), to a (possibly cv-qualified) base class of that type (or a reference to it), or to (possibly cv-qualified) void.

Also, with few exceptions, the choice of public/protected/private rarely changes what a program does, just whether a program is valid or not. So initialization directly binds a reference to subobject when possible rather than using a user-defined conversion, and after that choice is made, the compiler checks for access.

Upvotes: 2

Related Questions