2016-03-31 29 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(){ 

olarak B sınıfı özel Sınıf A devralıyorsa, bu upcasting çalışmak gerekiyordu değildir:Açık türetme neden özel miras için öngörüye izin veriyor?

A* a = new B; 

Ama açık tiplemeleri bunu izin veriyor. Neden?

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

C-cast çoğu dönüşüme izin verir (int * 'den' '* 'ye bile). Kullanım beklenen çıktı ile UB olabilir. – Jarod42

+0

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

cevap

18

A* a1 = (A*)new B; 

yılında döküm ulaşılmaz temel sınıf bir atıldı.

Yalnızca C stili bir döküm olarak ifade edilebilir. Bu durumda bir static_cast'un ne işe yaradığına eşdeğerdir ve bu durumda reinterpret_cast'a eşdeğer değildir. Özellikle sonuç adresi, argüman adresi ile aynı değildir.

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

reinterpret_cast ve const_cast cinsinden ifade edilen, geçerli bir yayın değil. –

+5

@RichardHodges: Erişilemez taban sınıfına, ve 'dynamic_cast' ve hatta genel durum için“ static_cast ”,“ reinterpret_cast ”ve“ const_cast ”terimleriyle ifade edilemez. Yani “Eğer reinterpret_cast ve const_cast açısından ifade edilemezse, bu geçerli bir döküm değildir” ifadesi anlamsız bir iddiadır. Afedersiniz. –

+1

Referansı görüyorum ve ayağa kalkıyorum. Teşekkür ederim. –

5

Açık döküm, istediğiniz her şeyi yapmanızı sağlar. Örneğin, şu şekilde yazabilirsiniz:

int *p = (int*)new B; 

ve kod derlenecek. Açık yayınlama, ne yaptığınızı bildiğiniz anlamına gelir.

+12

* Açık yayınlama, ne yaptığınızı bildiğiniz anlamına gelir . * => genellikle tam tersi. :-) – HostileFork

+0

^^ kesinlikle bu !!! –

+0

Açık döküm, derleyiciye "Ne yaptığımı biliyorum" diye bildiriyor –

8

Bu C-stil kuralları tarafından izin verilen atmalarını:

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

  • [...]

Bir static_cast değiştirmek, o zaman bu başarısız olur derlemek GCC bu hatayı veriyor:

error: 'A' is an inaccessible base of 'B' 
    A* a1 = static_cast<A*>(new B); 
1

açık tiplemeleri herhangi bir nesne yönelim özellikleri veya kurallar yoktur C dilinin bir programlama özelliğidir. C dili için her şey işaretçilerdir (belleğe veya işlevlere). Updcasting ve downcasting, C++ tarafından sağlanan nesne yönlendirme özellikleridir. Miras döküm, dilin nesne yönelim kurallarına uygun davranmalıdır. Ancak, nesneyi aşağıdaki gibi yazarak: A* a1 = (A*)new B;, derleyiciyi, bir yapının işaretçisini diğerine zorlayarak, A nesnesini C'ye yaptığınız gibi işlemek için 'u zorlayın. Bu nedenle, derleyici, dökümlenen nesnenin f() çağrı işaretçisinde atanacak hangi işlev işaretçisine karar verdiğinde, A sınıf uygulamasının işaretçisini atar.

+0

Bunun nedenini soracağından en uygun cevabı bu olduğunu düşünüyorum. –

İlgili konular