2010-08-17 21 views
7

$ 4.11/2 devletler -Pointer

B bir sınıf türü olan “türü B üyesi cv T, işaretçi” türünün bir rvalue, bir dönüştürülebilir

DB türetilmiş bir sınıfı (madde 10) Çeşidi rvalue “tipi cvT, bir D üyesine işaretçi”. B (10.2) belirsiz veya D bu dönüşümü gerektiren bir programın (10.1) taban sınıfı sanal bir erişilemez (madde 11) ise, kötü şekillendirilmiş olduğu. Biz BD sanal taban sınıfı olmama kısıtlama neden

Sorum şu?

cevap

0

Gerçekten ilginç bir soru. Bugün yeni bir şey öğrendim.

+-------------+ 
| A: int a; | 
+-------------+ 
| B: int b; | 
+-------------+ 
| A: int a; | 
+-------------+ 
| C: int c; | 
+-------------+ 
| D: int d; | 
+-------------+ 

D uçları:

class A { int a; } 
class B : public A { int b; } 
class C : public A { int c; } 
class D : public B, public C { int d; } 

İşte muhtemel bellek düzeni aşağıdaki gibidir: Casting member function pointers from derived class to virtual base class does not work

5

olmayan bir sanal temel sınıf kapsayan bir durum düşünün: Bu benim Konuya dair bulabildiğim ne B ve C'dan aldığı ve her ikisi de A alt nesnesine sahip olduğu için iki A alt nesnesine sahiptir.

Üye değişkenlere yönelik işaretçiler, genellikle nesnenin başlangıcından tamsayı sapması olarak uygulanır. Bu durumda, A nesnesindeki int a için tamsayı sapması sıfırdır. Yani "int a türünde A" işaretçisi, sıfırın bir tamsayı ofseti olabilir.

a "tipi A ait int a işaretçiyi" Bir dönüştürmek için "tip B ait int a için pointer," sen sadece B bulunan A altnesnesi (ilk A subobject) ofset bir tamsayı gerekir.

a "tipi A ait int a işaretçiyi" Bir dönüştürmek için "tip C ait int a için pointer," sen sadece C bulunan A altnesnesi (ikinci A subobject) ofset bir tamsayı gerekir. B ve C A göre nerede derleyici bildiğinden

, derleyici A den B veya C için downcast konusunda yeterli bilgiye sahiptir.

Şimdi sanal bir temel sınıf ile ilgili bir durum düşünün:

struct A { int a; } 
struct B : virtual public A { int b; } 
struct C : virtual public A { int c; } 
struct D : public B, public C { int d; } 

Olası bellek düzeni:

+-------------+ 
| B: ptr to A | ---+ 
| int b; | | 
+-------------+ | 
| C: ptr to A | ---+ 
| int c; | | 
+-------------+ | 
| D: int d; | | 
+-------------+ | 
| A: int a; | <--+ 
+-------------+ 

Sanal taban sınıfları genellikle (neredeyse A türetmek) B ve C alarak uygulanmaktadır Tek A subjobject için bir işaretçi içerir. A alt nesnesinin işaretçileri gereklidir, çünkü B ve C'a göre A konumu sabit değildir.

elimizde olan bir olsaydı "tip A ait int a için işaretçi," Biz değişebilir B ve C subobjects yeri beri, "tip B ait int a için pointer" Bir için döküm mümkün olmayacaktır A'a göre. A, B ya da için geri bildirim göstermez; bu nedenle, aşağı çalışan yayın için yeterli bilgiye sahip değiliz.

+0

+1 – Bill

1

Sanal olmayan devralma ile, temel sınıf ve türetilmiş sınıf üyeleri, temel sınıf ilk olarak bellekte bitişik olarak yerleştirilebilir, böylece her bir temel sınıf üyesi nesneye göre aynı konumdadır. nesnenin bir B veya D olup olmadığını adres. Bu, B işaretçiden üyeye bir işaretçi-a-D; her ikisi de nesnenin adresinden bir ofset olarak temsil edilebilir.

Sanal kalıtımla, temel sınıf üyelerine, temel sınıfın bulunduğu yeri belirten türetilmiş nesnede bir işaretçi (veya eşdeğeri) yoluyla erişilmelidir. Bu, bu indirmenin gerekli olduğunu belirtmek için işaretçi-üye temsiline fazladan bilgi eklemeyi gerektirir ve herhangi bir işaretçi-üyesi için kullanıldığında bir çalışma zamanı denetimi gerektirecektir.

C++ 'nun çoğunun ardındaki genel bir prensip, mümkün olan her durumda çalışma süresi yükünden kaçınmaktır. Bu durumda, seçim oldukça yaygın bir işlem üzerinde bir çalışma zamanı denetimi arasındaydı, oldukça belirsiz bir dönüşümü devre dışı bırakıyordu ve bu prensip burada uygulanmış görünüyor. ASCII sanat örnekleri için

İlgili konular