2016-03-31 13 views
24
#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(){ 

Wie Klasse B Klasse A privat erbt, diese Upcasting nicht funktionieren soll:Warum ermöglicht explizites Typcasting Upcasting für private Vererbung?

A* a = new B; 

Aber explizite Schublade gesteckt wird, ermöglicht wird. Warum?

A* a1 = (A*)new B; 
    a1->f(); 
    return 0; 
} 
+1

Der c-cast erlaubt die meisten Konvertierungen (sogar von 'int *' in 'A *'). Die Verwendung könnte dann UB mit erwarteter Ausgabe sein. – Jarod42

+0

Duplizieren: http://stackoverflow.com/questions/17925124/can-i-cast-a-derived-class-to-a-private-base-class-c –

Antwort

18

Die Besetzung in

A* a1 = (A*)new B; 

ist ein gegossenes an unzugänglicher Basisklasse.

Es kann nur als C-Style-Cast ausgedrückt werden. Es entspricht dem, was ein static_cast tun würde, wenn ein static_cast in dieser Situation verwendet werden könnte, und es ist nicht äquivalent zu einem reinterpret_cast. Insbesondere ist die Ergebnisadresse nicht notwendigerweise die gleiche wie die Argumentadresse.

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;

+2

Wenn es nicht sein kann ausgedrückt in reininterpret_cast und const_cast, ist es überhaupt kein gültiger Cast. –

+5

@RichardHodges: Cast in unzugängliche Basisklasse, und 'dynamic_cast', und sogar' static_cast' für den allgemeinen Fall, kann nicht in Begriffen von 'reininterpret_cast' und' const_cast' ausgedrückt werden. I.e. Ihre Aussage "Wenn es nicht in Bezug auf reinterpret_cast und const_cast ausgedrückt werden kann, ist es überhaupt kein gültiger Cast." ist eine Nonsense-Behauptung. Es tut uns leid. –

+1

Ich sehe die Referenz und Stand korrigiert. Vielen Dank. –

5

Explizites Casting ermöglicht es Ihnen, alles zu tun, was Sie wollen. Sie können zum Beispiel so schreiben:

int *p = (int*)new B; 

und der Code wird kompiliert werden. Explizite Besetzung bedeutet, dass Sie wissen, was Sie tun.

+12

* Explizite Besetzung bedeutet, dass Sie wissen, was Sie tun . * => normalerweise das Gegenteil. :-) – HostileFork

+0

^^ absolut das !!! –

+0

Explizite Umwandlung sagt dem Compiler, dass "Ich weiß, was ich tue" –

8

Dies wird durch die Regeln von C-Stil erlaubt ist, wirft:

(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;

  • [...]

Wenn Sie zu einem static_cast ändern, dann wird dies nicht gelingen kompilieren. GCC gibt diesen Fehler:

1

Die explizite Typecasting ist eine Programmierfunktion der C-Sprache, die keine Objektorientierungsfunktionen oder -regeln hat. Für die Sprache C ist alles ein Zeiger (auf Speicher oder Funktionen). Updcasting und Downcasting sind Objektorientierungsfunktionen, die von C++ bereitgestellt werden. Das Vererbungscasting muss sich auf die Objektorientierungsregeln der Sprache beziehen. Wenn Sie jedoch das Objekt wie folgt typisieren: A* a1 = (A*)new B; erzwingen Sie den Compiler , um das Objekt als A zu behandeln, genau wie in C, indem Sie einen Zeiger einer Struktur auf einen anderen erzwingen. Wenn der Compiler entscheidet, welcher Funktionszeiger auf dem f() Aufrufzeiger des gegossenen Objekts zuzuweisen ist, weist er daher den Zeiger der Klassenimplementierung A zu.

+0

Ich denke, das ist die relevanteste Antwort, da die Op fragt warum. –

Verwandte Themen