Cơ Chế Vptr và Vtable Trong Đa Kế Thừa C++

Cấu Trúc Bộ Nhớ Đa Kế Thừa

Khi lớp dẫn xuất kế thừa từ nhiều lớp cơ sở chứa hàm ảo, trình biên dịch tạo các con trỏ vptr độc lập cho mỗi lớp cơ sở. Mỗi vptr trỏ đến bảng hàm ảo (vtable) tương ứng, đảm bảo đa hình động hoạt động chính xác.

Minh Họa Bố Cục Bộ Nhớ

class ChaA {
public:
    virtual void phuongThucA() {}
};

class ChaB {
public:
    virtual void phuongThucB() {}
};

class Con : public ChaA, public ChaB {
public:
    void phuongThucA() override {}
    void phuongThucB() override {}
};

Bố cục bộ nhớ đối tượng Con:

Độ dờiNội dung
0vptr_ChaA
8vptr_ChaB

Nguyên Lý Phân Phối vptr

Trình biên dịch đặt vptr của lớp cơ sở chính tại vị trí đầu đối tượng, vptr lớp cơ sở thứ cấp tại vị trí tương ứng:

class BaseX { virtual void x() {} };
class BaseY { virtual void y() {} };
class Child : public BaseX, public BaseY {};
Độ dờiNội dung
0x00vptr_BaseX
0x08vptr_BaseY

Kỹ Thuật Thunk Điều Chỉnh Con Trỏ

Khi chuyển kiểu con trỏ giữa các lớp cơ sở, trình biên dịch sinh mã thunk để hiệu chỉnh con trỏ this:

_ZThn8_N5BaseY4funcEv:
    subq $8, %rdi
    jmp _ZN3Con4funcEv

Ảnh Hưởng Của Kế Thừa Kim Cương

Kế thừa ảo giải quyết vấn đề trùng lặp lớp cơ sở nhưng tăng chi phí:

class Nen { virtual void f() {} };
class NhanhA : virtual public Nen {};
class NhanhB : virtual public Nen {};
class Cuoi : public NhanhA, public NhanhB {};

Đối tượng chứa thêm con trỏ cơ sở ảo (vbptr), tăng kích thước và thời gian truy cập.

So Sánh Hiệu Năng

Loại kế thừaThời gian gọi (ns)Số vtable
Đơn kế thừa3.21
Đa kế thừa4.72

Tối Ưu Hóa vtable

Trình biên dịch giảm entry trùng lặp bằng cách:

  • Chia sẻ con trỏ hàm toàn cục
  • Nén các đoạn chỉ đọc
class Goc {
public:
    virtual void a() {}
    virtual void b() {}
};

class KeThua : public Goc {
    void a() override {}
};

Thẻ: C++ vptr vtable đa kế thừa con trỏ ảo

Đăng vào ngày 20 tháng 5 lúc 02:20