c++typecasting-operatorprivate-inheritance

Difference among three explicit upcasting to a private base class


I have the following three typecastings between the private inherited base class object and the child object, two of them work, but the last one doesn't. I am wondering what causes the different results.

#include<iostream>
#include <string>
using namespace std;
class test :private string
{
public:
    test(string st) :string(st){}
    void show();
};

void test::show()
{
    cout << (string)*this << endl; // typecasting 1, works, display "abcd"
}
int main()
{
    test a("abcd");
    a.show();

    cout << (string &)a << endl; //typecasting 2, works, display "abcd"

    cout<<(string )a<<endl;   //typecasting 3;  error C2243: 'type cast' : conversion from 'test *' to 'const std::basic_string<char,std::char_traits<char>,std::allocator<char>> &' exists, but is inaccessible     
}

Isn't a the same as '*this' - since both are objects? So why does No.1 work?
If it's because of scope, then why No.2 works? Could anyone please explain the mechanism behind each of them that make the difference among them?

Also, the first method seems to create a string object. In the private inherited case, base class reference can't be set to the derived class object. So how the temporary string object is created?

Thanks in advance.


Solution

  • test subclasses string privately, so test "knows" it is a string, but anyone outside doesn't.

    In your first case, what happens is as follows:

    1. Outside of test (in main), you call the show method. That's OK, because it's public.

    2. Now, inside show, the code "knows" it's of type string, because it's a method of test. The conversion is OK.

    In your third case, though, you're trying to do the conversion outside, from main. Outside of test, main "doesn't know" that test is a string.

    How does your second case work, then? You're performing a C-style cast from a derived to public base. Surprisingly, this is allowed (although not necessarily good style!). Quoting from the accepted answer there: §5.4/7 of the standard:

    ... the following static_cast and reinterpret_cast operations (optionally followed by a const_cast operation) may be performed using the cast notation of explicit type conversion, even if the base class type is not accessible: a pointer to an object of derived class type or an lvalue of derived class type may be explicitly converted to a pointer or reference to an unambiguous base class type, respectively;