2011-03-16 17 views
8

Sınıf hiyerarşisinde "çapraz döküm" yapmak için dynamic_cast'u kullanmak yasal olduğunu biliyorum. Ben sınıfları varsa Örneğin, bu gibi göründüğünü: Ben tip C bir nesneye işaret ediyor bir A* işaretçisi varsaÇapraz dönüşümün işe yarayıp yaramadığını kontrol etme?

A B 
    \/
    C 

, o zaman bir işaretçi almak için

A* aPtr = /* ... something that produces a C* ... */ 
B* bPtr = dynamic_cast<B*>(aPtr); 

kullanabilirsiniz C'un B temel nesnesini işaret ediyorum.

bu söz nedeni yukarıdaki kod yazmak zamanda, derleyici henüz A ve B görmüş olsa C tanımını görmediği mümkün olmasıdır. Bu, derleyicinin A ve B arasında herhangi bir bağlantı tespit etmemesinin mümkün olduğu anlamına gelir, ancak yine de kodu derlemek zorundadır çünkü C gibi bir sınıfın var olması ve dynamic_cast'un bazı durumlarda başarılı olması mümkündür. Sorun şu ki, yanlış türde bir nesneyi kazara çapraz olarak çevirebileceğim anlamına gelir.

İşte
A B D 
\/ 
    C 

, D bazı rasgele ilgisiz sınıftır: Ben şuna benzer sınıfları sahip olduğunu varsayalım. A ve D bağlamak için hiçbir olası yolu yoktur çünkü

A* aPtr = /* ... get a C* pointer ... */ 
D* dPtr = dynamic_cast<D*>(aPtr); 

O zaman bu dynamic_cast daima zamanında başarısız olur: Böyle bir şey yazmaya çalışırsanız. Yanlışlıkla D kullanıyorum, çünkü B kullanmak istediğimden derleyici, anlamsız bir döküm yapmam için bana hiçbir gösterge vermeyecektir.

Soruma ilişkin soru: Derleyicinin, alicinin çalışma zamanında her zaman başarısız olacağı konusunda beni uyarması için bir yol var mı? Bunu algılayabilen herhangi bir büyük derleyici için dil düzeyi bir çözümden veya bazı derleyici ayarlarından memnun olurum. Dış bir araç varsa, bu da iyi; Sadece bu sınıf hataları yakalamanın mümkün olup olmadığını bilmek istiyorum.

+0

Bu kesinlikle bağlayıcı seviyesinde olmalı? Derleme zamanında, “A” ve “D” den türeyen bir sınıf oluşturulamayacağınızı bilmiyorsunuz? – Keith

+0

@ Keith- Kesinlikle, her şeye sahip bir derleyiciniz olmadıkça. Dostum, ben bunlardan birini istiyorum ... :-) – templatetypedef

+0

@Keith: Bağlayıcı bile cevabımda açıklandığı gibi her tür hakkında tam bilgi sahibi olmayabilir. –

cevap

3

Bunu derleme zamanında algılamak mümkün değil. İlişkisini tanıtan C sınıfı, henüz yazılmamış olan dinamik olarak yüklenebilen bir kitaplıkta bulunabilir ve derleyici aksini ispatlayamaz.

Bununla birlikte bazı istisnalar olabilir.A sadece özel kuruculara (veya özel bir yıkıcıya) sahipse, derleyici, A tarafından arkadaş olarak adlandırılmamış yeni alt sınıfların olmayacağından emin olabilir.

+0

Bu kesinlikle doğru. Bununla birlikte, bir şekilde linker'i bana bir şey uyandırmak için "Hey, bunun şüphe uyandırdığını bilmene izin vermesi" mümkün olabilir mi? sorun olmaktan çıksa bile mi? – templatetypedef

+1

@templatetypedef: 'dynamic_cast' bir şablon işlevi gibi görünüyor ve hissediyor, belki bir sarıcı tanıtmak, sarıcı kullanımını zorlamak için '#define dynamic_cast checked_dynamic_cast' kullanın ve sonra bir şekilde şablonun tüm örneklenen sürümlerinin bir listesini alın ? Miras grafiğini almak oldukça kolaydır, örneğin doxygen'ın XML çıktısı da dahil olmak üzere bunu ortaya çıkaran birçok araç vardır. Bu bilgileri birleştirmek ve bazı buluşsal yöntemleri uygulamak, aradığınız uyarıyı size vermelidir. –

-3

Gerçek şu ki, dynamic_cast'u kullanırken, sınıflar birbiriyle ilgisiz olsa bile, herhangi bir polimorfik işaretçiyi herhangi bir polimorfik işaretleyiciye atabilirsiniz.

Derleme zamanı denetimi istiyorsanız, birçok durumda diğer nedenlerden dolayı uygun olmayan diğer yayınları (static_cast veya örtük dönüşümler) kullanmanız gerekir.

dynamic_cast gerektiğinde kullandığımız çözüm, dynamic_cast'u yapan ve boş bir işaretçi elde edilirse bir istisna atar. Elbette bu sadece bir çalışma zamanı kontrolü, ancak oldukça güvenilir.

+1

-1: Bir polimorfik sınıfı başka bir polimorfik sınıfa, yalnızca kendi RTTI'ları ilişkiliyse dinamik olarak yayınlayabilirsiniz. Aksi halde, 0 ptr (ptr'e gönderirseniz) veya ilgili olmayan polimorfik sınıfa ref döndüğünde bir bad_cast istisnası alırsınız. – TrueY

0

Bu dinamik dökümün tüm anlamı: Dinamik, yani çalışma zamanında derleme zamanında değil kontrol edilir.

Derleyici yalnızca döküm sınıflarının polimorfik olup olmadığını kontrol eder. Eğer sınıflar polimorfik değilse, o zaman dökümün çalışma zamanında kontrol edilmesi için yeterli bilgi olmayacaktır.

Ve son olarak dinamik dökümden sonra program, alınan işaretçinin boş olup olmadığını kontrol etmelidir. Bir referansa gönderirseniz, std :: bad_cast öğesini yakalamanız gerekir.

İlgili konular