2017-05-24 15 views
5

Tôi đang cố gắng để undestand một số điều cấp thấp với bảng ảo và thừa kế.Sự hiểu biết về vtable trong các lớp học có nguồn gốc

Khi bạn tạo lớp mới bằng cách kế thừa hai lớp và thêm các hàm ảo mới, nơi chính xác vptr sẽ được lưu trữ?

Dường như với tôi, trình biên dịch đó thực hiện một số 'tối ưu hóa vptr' trong trường hợp đó. Và tôi đang cố gắng tìm ra.

Giả sử, chúng ta có cấu trúc như sau:

struct A 
{ 
    int a; 
    virtual void fa(); 
}; 
struct B 
{ 
    double b; 
    virtual void fb(); 
}; 
struct C : A, B 
{ 
    char c; 
    virtual void fa(); 
    virtual void fb(); 
    virtual void fc(); 
}; 

Trong trường hợp của x86 và align = 4, AB trong bộ nhớ sẽ trông như thế này:

+------+------+ 
A: | vptr | a | 
    +------+------+ 
sizeof(A) = 4 + 4 = 8 

    +------+------+------+------+ 
B: | vptr  |  b  | 
    +------+------+------+------+ 
sizeof(B) = 8 + 8 = 16 

Nhưng khi tôi cố gắng Lắp ráp lại C, tôi có được điều này:

+------+------+------+------+------+------+------+ 
C: | vptr | a | vptr  |  b  | c | 
    +------+------+------+------+------+------+------+ 
but sizeof(C) = 32 

С с; 
(C*)&c; // 0x100 
(B*)&c; // 0x108 
(A*)&c; // 0x100 
&c.a; // 0x104 
&c.b; // 0x110 
&c.c; // 0x118 

Vì vậy whe lại là vptr của C? Tôi có thể cho rằng trình biên dịch rằng hợp nhất bảng ảo khác nhau, nhưng trong trường hợp đó tại sao sizeof(C) lợi nhuận sizeof(A) + sizeof(B) + sizeof(alligned_char) + sizeof (vptr)

Các struct D : public C {} có những câu chuyện tương tự (ví dụ vptr của AC.) - có không có vptr của D.

Trình biên dịch tôi sử dụng là msvc 2012 x86.

+1

tại sao vptr trong struct B cần 8 byte? – walker

+1

@walker Tôi nghi ngờ điều đó. Nó có lẽ là một số đệm. – luk32

+3

Có thể trùng lặp của [Bao nhiêu vptr sẽ là một đối tượng của lớp (sử dụng đơn/đa thừa kế) có?] (Https://stackoverflow.com/questions/3342035/how-many-vptr-will-a-object-of- classuses-single-multiple-inheritance-have) – Andrew

Trả lời

4

Trình biên dịch phải sắp xếp sự đơn giản, với thực tế là các lớp cơ sở cần tồn tại trong đối tượng.

+------+---------+----+ 
| A | B  | C | 
+------+---------+----+ 

Vì vậy

  • A có nhu cầu tồn tại như thể nó đã không có nguồn gốc.
  • B cần tồn tại như thể nó không có nguồn gốc.
  • C có quyền tự do mới.

chức năng ảo từ A và B sẽ được vá cho triển khai của lớp dẫn xuất C. C sẽ thêm các hàm ảo vào (có thể) thành phần đầu tiên hiện tại A s vtable.

cơ sở vtable cho A

+------+ 
| A:fa | 
+------+ 

vtable cho A trong lớp có nguồn gốc C

+------+ 
| C:fa | // implemented by derived class. 
+------+ 
| C:fb | // any calls to fb need to be sent to `C`'s implementation 
+------+ 
| C:fc | // any calls to fc can be overridden by vtable. 
+------+ 

vtable cho B trong lớp có nguồn gốc C

+------+ 
| C:fb | // overridden, but no need to add fc, fa to this table. 
+------+ 

Tôi nghĩ quy tắc liên kết là mối quan hệ ng kích thước của C sẽ được đệm sao cho liên kết gấp đôi nhạy cảm được căn chỉnh chính xác (đảm bảo rằng một mảng C được căn chỉnh chính xác).

Kích thước của B là kích thước của (4) vptr và đệm để đảm bảo double được thẳng hàng (4) và kích thước của double (8)

+1

Có, hóa ra chỉ là căn chỉnh, chứ không phải một vptr mới. – renzo

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