4

I have seen this example from the book:

class Test: private std::string
{
public:
    Test():std::string("How?")
    {
    }
};

int main(int argc, char** argv)
{
    Test t;

    std::cout<<(std::string&)t<<std::endl;

    return 0;
}

I don't know how did it printed "how" when i typecasted the class name? is it because of operators? but i know that when you do private inheritance, the public and protected variables and methods will be considered "private" outside.

So my question is, how did it exactly printed "How" ?

edit :

so who is holding the string value "How" and how was it printed? Because it was printed by typecasting.

Carlos Miguel Colanta
  • 2,465
  • 3
  • 27
  • 46

2 Answers2

6

This illustrates one of the dangers of the C-style cast : it's the only cast that ignores inheritance access specifiers. As you saw, the cast successfully dug out the std::string base reference, even though it was private. If you try this with a static_cast, it won't compile.

Edit :

The std::string subobject of t is holding "How", as you initialized it in Test's constructor. Casting to a reference to a base class serves to access the corresponding subobject.

Quentin
  • 60,592
  • 7
  • 125
  • 183
  • Well, i saw this technique from the book "C++ primer" so i kinda wondered. – Carlos Miguel Colanta May 26 '15 at 07:18
  • 1
    @CarloBrew A book that suggests c-style casts is a bit dated, and a book that suggests inheriting from a std container is giving bad advice. – acraig5075 May 26 '15 at 07:20
  • @acraig5075 depends on the context. As long as you always inherit privately if your base class is not virtual-destructible, and you use C-style cast with care and parsimony, everything's fine. – Quentin May 26 '15 at 07:22
  • *"[C-style cast is] the only cast that ignores inheritance access specifiers"* - a `reinterpret_cast` could be used to do this too. – Tony Delroy May 26 '15 at 07:24
  • So the code `(std::string&)t` made it point to the base class? – Carlos Miguel Colanta May 26 '15 at 07:35
  • 1
    @TonyD: No, `reinterpret_cast` would pretend there's a `string` at the same address, giving undefined behaviour if it isn't a standard-layout type. An evil C cast will correctly adjust the address to refer to the base-class subobject, as `static_cast` would if the base class were accessible. – Mike Seymour May 26 '15 at 07:35
  • @TonyD As long as `Test` is a standard-layout type with the `std::string` as first base, yes. But `reinterpret_cast` ignores pretty much everything, so I'm not sure it's worth mentioning it here. – Quentin May 26 '15 at 07:36
  • @CarloBrew yes. The base-class part of `t`, that is. – Quentin May 26 '15 at 07:37
  • 1
    @MikeSeymour: I'm not saying it's better or equivalent or safe, just highlighting that it can also bypass the access specifiers as the text I quoted implied no "new-style" casts were capable of that. Quentin: suit yourself - it's mentioned now in comments anyway for anyone else pedantic enough to read that far.... – Tony Delroy May 26 '15 at 09:54
3

The cast (std::string&)t casts t to a reference to an instance of its base class std::string. C style casts are the only casts that can cast to an inaccessible base class. The effect is the same as with an ordinary implicit conversion to an accessible base class.

Cheers and hth. - Alf
  • 138,963
  • 15
  • 198
  • 315