25
#include<iostream>
using namespace std;

class A {
    public:
    void f(){cout<<"A"<<endl;}
};

class B : private A {
    public:
    void f(){cout<<"B"<<endl;}
};

int main (){

As Class B is inheriting Class A privately, this upcasting is not supposed to work:

    A* a = new B;

But explicit typecasting is allowing it. Why?

    A* a1 = (A*)new B;
    a1->f();
    return 0;
}
Sled
  • 18,541
  • 27
  • 119
  • 168
Dblaze47
  • 868
  • 5
  • 17
  • 1
    The c-cast allows most conversion (even from `int*` into `A*`). The usage then might be UB with expected output. – Jarod42 Mar 31 '16 at 08:05
  • Duplicate: http://stackoverflow.com/questions/17925124/can-i-cast-a-derived-class-to-a-private-base-class-c – M.M Mar 31 '16 at 08:45

4 Answers4

19

The cast in

A* a1 = (A*)new B;

is a cast to inaccessible base class.

It can only be expressed as a C style cast. It is equivalent to what a static_cast would do if a static_cast could be used in this situation, and it is not equivalent to a reinterpret_cast. In particular the result address is not necessarily the same as the argument address.

C++11 §5.4/4:

The same semantic restrictions and behaviors [as for a static_cast] apply [for a C style cast], with the exception that in performing a static_cast in the following situations the conversion is valid even if the base class is inaccessible:

— a pointer to an object of derived class type or an lvalue or rvalue of derived class type may be explicitly converted to a pointer or reference to an unambiguous base class type, respectively;

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • 2
    If it can't be expressed in terms of reinterpret_cast and const_cast, it's not a valid cast at all. – Richard Hodges Mar 31 '16 at 08:25
  • 5
    @RichardHodges: Cast to inaccessible base class, and `dynamic_cast`, and even `static_cast` for the general case, can't be expressed in terms of `reinterpret_cast` and `const_cast`. I.e. your statement that “If it can't be expressed in terms of reinterpret_cast and const_cast, it's not a valid cast at all.” is a nonsense assertion. Sorry. – Cheers and hth. - Alf Mar 31 '16 at 08:26
  • 1
    I see the reference and stand corrected. Thank you. – Richard Hodges Mar 31 '16 at 08:27
8

This is allowed by the rules of C-style casts:

(N3337) [expr.cast]/4: The conversions performed by

  • a const_cast (5.2.11),
  • a static_cast (5.2.9),
  • a static_cast followed by a const_cast,
  • a reinterpret_cast (5.2.10), or
  • a reinterpret_cast followed by a const_cast,

can be performed using the cast notation of explicit type conversion. The same semantic restrictions and behaviors apply, with the exception that in performing a static_cast in the following situations the conversion is valid even if the base class is inaccessible:

  • a pointer to an object of derived class type or an lvalue or rvalue of derived class type may be explicit converted to a pointer or reference to an unambiguous base class type, respectively;

  • [...]

If you change to a static_cast, then this will fail to compile. GCC gives this error:

error: 'A' is an inaccessible base of 'B'
    A* a1 = static_cast<A*>(new B);
TartanLlama
  • 63,752
  • 13
  • 157
  • 193
5

Explicit casting allow you to do everything you want. You can, for example, to write so:

int *p = (int*)new B; 

and the code will be compiled. Explicit cast means that you know what you are doing.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
Alexey Subbota
  • 938
  • 6
  • 23
1

The explicit typecasting is a programming feature of C language which doesn't have any object orientation features or rules. For C language everything is pointers (to memory or functions). Updcasting and downcasting are object orientation features provided by c++. The inheritance casting must behave on the object orientation rules of the language. However, by typecasting the object like this: A* a1 = (A*)new B; you force the compiler to treat the object as A just as you would do in C by forcing a pointer of a struct to another. Therefore, when the compiler decides which function pointer to assign on the f() calling pointer of the casted object it assigns the pointer of the A class implementation.

E. Ladakis
  • 11
  • 1