3

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.

Flowing Cloud
  • 433
  • 1
  • 4
  • 8
  • You cannot really do inheritance casting with direct values. This usually only works with pointers and references. `*this` is a `const&` thats why it "works" here. same for `string &`. But you cannot really cast one type into another with using direct values. I am also not sure if your casts have some negative side effects at some point (casting a ref to a value and vice versa). Also for others: I understand that this is test code but please do not code like that in real projects ;) – Hayt Sep 01 '16 at 08:22
  • Thanks a lot. May I ask how the temporary string obj is created when base class reference can't be set to the derived class object? Does it secretly treat `*this` as the reference to a base class when we do the explicit upcasting? Also, I won't do this in a real project :) I came across it by a typo.. – Flowing Cloud Sep 01 '16 at 08:37
  • You mentioned `*this` is a `const &` type. Could you please point me to some reference. I am sorry I looked it up but didn't find the relevant info (possibly because the key words are too widely used.) Thanks – Flowing Cloud Sep 01 '16 at 09:14
  • Figures I was not 100% correct there. this is only a const ptr in a const function. so in this case it's just a normal pointer and dereferencing it would result in a normal reference. The * operator usually returns a reference to the object. But I can't really point you to anything written that defines this now sadly :( – Hayt Sep 01 '16 at 09:27
  • I was surprised that dereferencing a pointer results in a reference. I thought it resulted in the variable/object. No problem. I'll look for it. Thanks~ – Flowing Cloud Sep 01 '16 at 09:36
  • I tested it: http://cpp.sh/6du4 does not copy (if i replace `auto&` with `auto` though it does) – Hayt Sep 01 '16 at 10:00
  • Wow, that's very surprising. Thank you very much. – Flowing Cloud Sep 01 '16 at 10:09

1 Answers1

2

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;

Community
  • 1
  • 1
Ami Tavory
  • 74,578
  • 11
  • 141
  • 185
  • Thanks a lot. May I ask how the temporary string obj is created when base class reference can't be set to the derived class object? Is it also because inside the 'test' class, they know the inheritance so the base class reference can be set to a private derived class object? – Flowing Cloud Sep 01 '16 at 08:47
  • @FlowingCloud Are you talking about the first case? – Ami Tavory Sep 01 '16 at 08:50
  • @FlowingCloud Within the `show` method, though, `test` is a perfectly valid `string` object too (this is what private inheritance means). So the code means "cast the `string` part of `*this` to a `string`". Does this answer your question? – Ami Tavory Sep 01 '16 at 09:15
  • Yes, perfectly. Thank you a lot. – Flowing Cloud Sep 01 '16 at 09:15