2010-01-31 32 views
8

Trong C struct, tôi đang đảm bảo rằng:Đảm bảo về địa chỉ của baseclass trong C + +?

struct Foo { ... }; 
struct Bar { 
    Foo foo; 
    ... 
} 
Bar bar; 
assert(&bar == &(bar.foo)); 

Bây giờ, trong C++, nếu tôi có:

class Foo { ... }; 
class Bar: public Foo, public Other crap ... { 
    ... 
} 

Bar bar; 
assert(&bar == (Foo*) (&bar)); // is this guaranteed? 

Nếu vậy, bạn có thể cho tôi một tài liệu tham khảo (như "The C++ Programming Ngôn ngữ, trang xyz ")?

Cảm ơn!

Trả lời

10

Không có bảo đảm. Từ tiêu chuẩn C++ 03 (10/3, class.derived):

Thứ tự trong đó lớp con subobject được phân bổ trong đối tượng có nguồn gốc cao nhất (1.8) không được chỉ định.

+1

Ghi nhận; cảm ơn. :-) g ++ gần như khiến tôi tin rằng điều đó đã được đảm bảo. – anon

+0

Như một lưu ý phụ, tiêu chuẩn hứa hẹn rất ít về cách bố trí các loại không POD - về cơ bản chỉ là thứ tự địa chỉ của các thành viên dữ liệu không tĩnh không được phân tách bởi một trình thông số truy cập can thiệp sẽ khớp với thứ tự khai báo (nhưng chỉ trong cùng 'phần truy cập-specifier'). –

1

Tôi không tưởng tượng được, tôi không biết tại sao nó cần phải như vậy.

Tôi có câu hỏi liên quan.

nếu bạn có thừa kế kim cương:

class Base(){ virtual void AFunc(){} }; 

class A:Base{}; 
class B:Base{void AFunc(){} } 

class Test:A,B{}; 


Base * b = (Base*)new Test; 

b->AFunc(); 

cho phép giả định rằng cấu trúc bộ nhớ là cơ sở: A: B: Kiểm tra,

lưu ý tại thời điểm gọi, tất cả các trình biên dịch biết là địa chỉ của sự bắt đầu của đối tượng và AFunc được mong đợi là tương đối so với đầu của đối tượng B, hai địa chỉ này sẽ không giống nhau! Vì vậy, làm thế nào nó hoạt động?

như thế nào nếu b là loại B, hai địa chỉ sẽ là như nhau ...

+0

@matt: Vui lòng đặt câu hỏi mới. – kennytm

+0

Đây chính xác là ví dụ trong 5.4/5 (nhưng với các vấn đề về khả năng truy cập bổ sung) và không đúng định dạng (cần có trình chẩn đoán từ trình biên dịch). –

6

Mặc dù bố trí cho các lớp cơ sở là not guaranteed theo cách bạn dường như đã được suy nghĩ (và mặc dù có rất nhiều đảm bảo cho các thành viên), điều này được đảm bảo:

Bar bar; 
assert(&bar == (Foo*) (&bar)); 

Bởi vì các diễn viên sử dụng một static_cast (mỗi 5.4) mà sẽ chuyển đổi &bar một cách chính xác, và sự so sánh giữa con trỏ-to-base và con trỏ-to-có nguồn gốc sẽ chuyển đổi tương tự .

này, tuy nhiên, sẽ không được đảm bảo:

Bar bar; 
void* p1 = &bar; 
void* p2 = (Foo*)&bar; 
assert(p1 == p2); // not guaranteed 
+0

@Roger: Một điểm rất tốt về chuyển đổi 'static_cast'. –

Các vấn đề liên quan