Tôi đang đọc bài viết này "Virtual method table"bảng phương thức ảo cho nhiều thừa kế
Ví dụ trong bài viết ở trên:
class B1 {
public:
void f0() {}
virtual void f1() {}
int int_in_b1;
};
class B2 {
public:
virtual void f2() {}
int int_in_b2;
};
class D : public B1, public B2 {
public:
void d() {}
void f2() {} // override B2::f2()
int int_in_d;
};
B2 *b2 = new B2();
D *d = new D();
Trong bài viết này, tác giả giới thiệu rằng việc bố trí bộ nhớ của đối tượng d
như sau:
d:
D* d--> +0: pointer to virtual method table of D (for B1)
+4: value of int_in_b1
B2* b2--> +8: pointer to virtual method table of D (for B2)
+12: value of int_in_b2
+16: value of int_in_d
Total size: 20 Bytes.
virtual method table of D (for B1):
+0: B1::f1() // B1::f1() is not overridden
virtual method table of D (for B2):
+0: D::f2() // B2::f2() is overridden by D::f2()
Câu hỏi là về d->f2()
. Các cuộc gọi đến d->f2()
qua một con trỏ B2
như một con trỏ this
vì vậy chúng tôi phải làm một cái gì đó như:
(*(*(d[+8]/*pointer to virtual method table of D (for B2)*/)[0]))(d+8) /* Call d->f2() */
Tại sao chúng ta phải vượt qua một con trỏ B2
như con trỏ this
không phải là gốc D
con trỏ ??? Chúng tôi đang thực sự gọi D :: f2(). Dựa trên sự hiểu biết của tôi, chúng ta nên vượt qua một con trỏ D
như this
đến D :: f2) chức năng (.
___update____
Nếu đi qua một con trỏ B2
như this
đến D :: f2(), gì nếu chúng ta muốn truy cập các thành viên của B1
lớp trong D :: f2() ?? Tôi tin rằng con trỏ B2
(this) được hiển thị như thế này:
d:
D* d--> +0: pointer to virtual method table of D (for B1)
+4: value of int_in_b1
B2* b2--> +8: pointer to virtual method table of D (for B2)
+12: value of int_in_b2
+16: value of int_in_d
Nó đã có một số offset của địa chỉ bắt đầu của cách bố trí bộ nhớ tiếp giáp này. Ví dụ, chúng tôi muốn truy cập b1
bên trong D :: f2(), tôi đoán trong thời gian chạy, nó sẽ làm một cái gì đó như: *(this+4)
(this
trỏ đến cùng một địa chỉ như b2) mà sẽ chỉ b2
trong B
????
(1) ý bạn là gì bởi "hoán đổi cho nhau", bạn có thể giải thích chi tiết hơn một chút không? (2) Nếu chuyển một con trỏ 'B2' thành' this' tới D :: f2(), thì nếu chúng ta muốn truy cập các thành viên của lớp B1 trong D :: f2() thì sao? Đối với (2), vui lòng xem nội dung cập nhật của câu hỏi. – Fihop
Cảm ơn rất nhiều !! Vui lòng xác minh tôi. 'B2 b2; b2.test() ', đó là một con trỏ' B2' được chuyển thành 'this' thành' B2 :: test() 'vì' b2' là một đối tượng độc lập. Đối với 'D d; d.test() ', trình biên dịch truyền con trỏ sửa lỗi thực sự trỏ đến đối tượng con' B2' của 'D' như' this' to 'test()' vì hàm gọi thực sự là 'B2 :: test() '. Nếu 'this' không trỏ đến' B2' bên trong 'D', nó sẽ gây ra vấn đề khi truy cập vào các thành viên của' B2' bên trong hàm 'B2 :: test()'. Đây là lý do tại sao tôi nghĩ rằng chúng ta nên vượt qua một con trỏ sửa chữa như 'this'. Ví dụ này không thể giải thích bản cập nhật. Cảm ơn vẫn còn – Fihop
Đối với 'D d; d.test() ', tôi đồng ý chúng ta làm một cái gì đó giống như' d.test (B2 * b2) '(có nghĩa là' this' trỏ đến phụ đối tượng 'B2' của D). Tuy nhiên, bên trong 'B2: test',' b2-> f2() 'nên thực thi' D :: f2'. Tôi có đúng không? Bây giờ vấn đề trở thành loại 'này' được chuyển tới' b2-> f2() ' – Fihop