2012-09-20 28 views
9

Aşağıdaki kodların davranışlarını açıklayan var mı?Adresler, yeniden yazım ve çoklu kalıtım

  1. Neden yani b2 == &d doğrudur, ilk durumda b = 3 var mı?
  2. Neden Durum 2'de sorun yok? b2 ve d adreslerini yazdım ve bunlar farklı. Eğer B için bir işaretçi C için bir işaretçi dönüştürmek zaman
#include <iostream> 

using namespace std; 

class A 
{ 
public: 
    A() : m_i(0) { } 

protected: 
    int m_i; 
}; 

class B 
{ 
public: 
    B() : m_d(0.0) { } 

protected: 
    double m_d; 
}; 

class C 
    : public A 
    , public B 
{ 
public: 
    C() : m_c('a') { } 

private: 
    char m_c; 
}; 

int main() 
{ 
    C d; 
    B *b2 = &d; 

    cout << &d << endl; 
    cout << b2 << endl; 

    const int b = (b2 == &d) ? 3 : 4; ///Case1: b = 3; 
    const int c = (reinterpret_cast<char*>(b2) == reinterpret_cast<char*>(&d)) ? 3 : 4; //Case 2: c = 4; 

    std::cout << b << c << std::endl; 

    return 0; 
} 
+0

+1, bunun iyi bir örnek olduğunu ve çok sayıda mirasın etkilerini çok iyi bir şekilde gösterdiği için – ltjax

+0

+1 aynı şekilde. Özellikle zil aracılığıyla insanları gerçekten göndermek için orada hiçbir sanal ile mükemmel bir örnek. – WhozCraig

cevap

9

D, (örneğin, ajustement genel olarak gerekli olan C ve oda altnesnesi işaret eden, bu şekilde ayarlanır tip C arasında olduğu Birden fazla kalıtımla, eğer B için gerek görülmezse, A'nın hem A hem de B'den miras olarak A için bir tane olması gerekirdi. Böylece atama ve karşılaştırma zamanında ayarlama yapılır. İki Diğer zamanlarda

, & d dönüştürülür ya hükümsüz * (örtük) ya da karakter * (a reinterpret_cast ile) ve yapılır hiçbir ayar (eğer reinterpret_cast ile hiçbir ayarlama için açıkça istedi ve hiçbir neden orada void * 'e dönüştürürken bir ayarlama yapmak, sadece iyi bir nedenden ötürü gidiş gelişi zorlaştırır, yine A) için benzer bir sonuca sahip olursunuz, bu yüzden temsil farklıdır.

BTW, reinterpret_cast<B*>(&d)'u kullandıysanız, hiçbir ayarlama yapılmayacaktı, ancak B * değeri olarak kullanmak sorunlara hızla yol açacaktır.

3

1 durumunda, karşılaştırma otomatik olarak C işaretçisini B işaretçisine atar. Bu durumda, bu, gerçek adresin değiştiğinden, birden çok devralma kullandığınız ve B'nin temel sınıflar listenizde ikinci olduğu anlamına gelir. Daha spesifik olması için, işaretçinin (en azından) boyut (A) ile dengelenmesi gerekir. Bununla birlikte, ikinci durumda, böyle bir otomatik dönüştürme gerçekleştirilmez, bu yüzden "A öneki" iki göstericiyi eşitsiz kılar.

+0

"Otomatik yayın" diye bir şey yoktur. Bir yayın, açık bir dönüşümdür, kaynak kodunda bulunur. – curiousguy

+0

Bununla ne demek istiyorsun? Açıkça 1 durumunda bir upcast var, ama açık değil. – ltjax

+0

Açık olmayan bir döküm sadece bir döküm değildir. Bir cast C stili, fonksiyonel stil veya yeni stil olabilir: '(T) x',' T (x) ',' static_cast (x) '... – curiousguy