2011-08-26 43 views
9

Tôi mới làm quen với tôi :) Từ những gì giảng viên của tôi đã nói trước đây, thứ tự của bảng ảo là quan trọng. Nhưng tôi không hiểu lý do cho điều đó !!?Thứ tự của bảng ảo có quan trọng không?

Với các mã tiếp theo:

class A 
{ 
public: 
    A() {cout <<"1" << endl;}; 
    A (const A& s) {cout << "2" << endl;} 
    ~A() {cout << "3" << endl;} 
    void f1() {cout << "4" << endl; f2();} 
    virtual void f2() = 0; 
    virtual void f3() {cout << "5" << endl;} 

}; 


class B : public A 
{ 
public: 
    B() {cout << "6" << endl;} 
    B(const B& b) : A(b) {cout << "7" << endl;} 
    ~B() {cout << "8" << endl;} 

    virtual void f1() {cout<<"9"<<endl;} 
    void f2() {cout<<"lO"<<endl; f4();} 
    virtual void f2(int i) {cout << "11" << endl;} 
    virtual void f4() {cout << "12" << endl; f3();} 

}; 

Ông nói rằng thứ tự là:

A's vtable : 
A::f2() 
A::f3() 

B's vtable : 
B::f2() 
A::f3() 
B::f1() 
B::f2(int) 
B::f4() 

Nhưng tôi không hiểu tại sao nó lại quan trọng? Ông nói rằng vtable là vô ích nếu nó là không theo thứ tự đúng của nó, bạn có thể vui lòng giải thích tại sao?

Trả lời

8

Thứ tự của vtable là quan trọng đối với mọi thứ hoạt động bình thường, nhưng chỉ với trình biên dịch (nghĩa là bạn không cần phải quan tâm vì nó sẽ xử lý nó).

Nếu trình biên dịch đưa nó ra khỏi trật tự cho chính nó, thì vâng, mọi thứ sẽ bị hỏng, bởi vì các hàm được tra cứu theo độ lệch (do đó bù trừ sẽ mang lại một hàm ngẫu nhiên sẽ là thảm họa). t cần phải lo lắng về những gì trật tự vtable được in

1

Bảng vtable là bảng "tra cứu". Về cơ bản nó là bản đồ của các con trỏ tới các hàm ảo của lớp. Nếu nó không đúng thứ tự, các con trỏ sẽ trỏ đến các hàm sai. Những điều xấu sẽ xảy ra nếu ví dụ bạn muốn gọi B:f1(), không có đối số, nhưng thay vào đó được gọi là B::f2(), mất int.

16

Không có khái niệm về vtables trong tiêu chuẩn C++. Nó chỉ là hầu hết các triển khai (nếu không phải tất cả) sử dụng nó cho công văn ảo. Các quy ước chính xác, tuy nhiên, được thực hiện hoàn toàn xác định.

Điều đó nói rằng ... Thứ tự của các hàm là quan trọng, nhưng không phải cho lập trình viên, nhưng đối với trình biên dịch - bạn có thể sắp xếp các chức năng của mình theo cách bạn muốn trong mã của mình. Trình biên dịch, tuy nhiên, thường sẽ đặt mỗi con trỏ hàm vào một vị trí cụ thể trong vtable, mà nó đã dành riêng cho hàm đó. Vì vậy, khi cần gọi f() nó biết chỉ số của hàm f() và lấy con trỏ đó từ vtable.

Câu hỏi này có thể giúp bạn cũng như: Virtual dispatch implementation details

+0

cảm ơn bạn rất nhiều !!! cho tất cả các bạn! –

+1

@Ron_s đảm bảo bạn nhấp vào dấu kiểm ở trên cùng bên trái của câu trả lời này nếu nó trả lời câu hỏi của bạn. –

2

Mỗi khách hàng của vtable cần biết đúng thứ tự để họ có thể tìm ra phương pháp đúng để gọi. Nhưng miễn là tất cả các bên đồng ý về án lệnh, không quan trọng trật tự đó là gì.

5

Điều này chỉ quan trọng khi các lớp khai báo giao diện cho ABI bên ngoài (ví dụ: COM/XPCOM).

Phần lớn thời gian không quan trọng và không có lý do gì để quan tâm đến nó.

+1

+1 abi bên ngoài là một điểm rất tốt –

+2

+1 Lý do duy nhất bố cục vtable là tiêu chuẩn trên nền tảng Windows là vì COM. Là một nhà cung cấp trình biên dịch, nếu bạn muốn hỗ trợ COM, bạn phải tuân thủ thực hiện của Microsoft. Tuy nhiên, các tính năng nâng cao hơn không được sử dụng bởi COM, chẳng hạn như thừa kế ảo hoặc nhiều thừa kế của các giao diện không phải là phụ thuộc thực hiện. –

0

Tôi không chắc chắn về những gì ông muốn nói, nhưng tôi sẽ cố gắng giải thích cách hoạt động:

Trước hết, C++ xác định phương pháp theo tên và chữ ký. Vì vậy, khi C++ khởi tạo một bảng ảo của lớp, nó sẽ thay thế tất cả các hàm ảo của lớp cơ sở bằng các hàm ảo có nguồn gốc có cùng tên và chữ ký.

Khi lớp học bắt nguồn từ một lớp khác, nó thực sự được xây dựng trên đó.Vì vậy, lớp cơ sở tồn tại như một phần của khối bộ nhớ (Phức tạp, đọc ở đây - Virtual inheritance)

Các bảng ảo chỉ giữ một "con trỏ" đến đúng chức năng tùy thuộc vào loại tại thời gian chạy.

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