2010-01-31 31 views
6

Kính thưa Ngài!cách C++ thực hiện đa hình trong nội bộ?

tôi nên nói với bạn rằng những gì tôi biết và những gì tôi không biết về câu hỏi được hỏi để bạn có thể giải quyết khu vực yếu của sự hiểu biết của tôi.

tôi biết rằng C++ thực hiện đa hình bằng cách sử dụng Vtable là mảng con trỏ mỗi con trỏ trỏ đến hàm ảo của lớp, mỗi lớp trong cấu trúc phân cấp có vtable. bây giờ giả sử tôi có lớp sau

class person 
{ 
    char name[20]; 
public: 
    person(char* pname) 
    { 
     strcpy(name,pname); 
    } 

    virtual void show() 
    { 
     cout<<"inside person show method, Name: "<<name; 
    } 
}; 

class teacher:public person 
{ 
    int scale; 

    teacher(char*pname, int s):person(pname) 
    { 
     scale=s; 
    } 

    void show() 
    { 
     cout<<"inside the teacher show method, Scale: "<<scale; 
    } 
}; 

bây giờ giả sử tôi viết trong chương trình chính

person *ptr; 
ptr=new teacher(16,"Zia"); 
ptr->show(); 

bây giờ tôi đang nhầm lẫn vào thời điểm này, cuộc gọi sẽ được chuyển tới các chương trình chức năng của lớp cơ sở, bây giờ vì nó là một hàm ảo nên nó inturn gọi hàm approprite. tôi biết tôi sai ở đây. tôi bối rối rằng những gì sẽ là chuỗi các cuộc gọi. Vai trò của Vtable là gì và nó hoạt động như thế nào.

+2

"Tôn trọng Sir"? Nghiêm túc? Nó nên là "Tôn trọng Sir * s *!" vì chúng tôi rất nhiều ...;) Tôi luôn tự hỏi tại sao một số người dùng bắt đầu với kính ngữ, nó hơi cổ xưa. – Spoike

+0

Zia, xin vui lòng tìm hiểu cú pháp Markdown: http://stackoverflow.com/editing-help – avakar

+0

@Zia ur Rahman: có một cái nhìn tại qn http://stackoverflow.com/questions/2092283/how-functions-are-resolved -by-compiler, giải thích khi trình biên dịch thực hiện một cuộc gọi đa hình và khi nó sẽ được gọi trực tiếp .. –

Trả lời

6

Tôi nghĩ bạn nên chú ý đến cuốn sách của Stanley B. Lippman "Inside C++ object model".

Cho phép xem xét để trình bày nội bộ cho lớp học của bạn:

Bảng ảo cho người và giáo viên

|---------------| +---> |------------------------| 
| name   | |  | "type_info" for person | 
|---------------| |  |------------------------| 
|__vptr__person |--+  | "person::~person"  | 
|---------------|  |------------------------| 
person p;    | "person::show"   | 
         |------------------------| 

|----------------| +---> |-------------------------| 
|person subobject| |  | "type_info" for teacher | 
|----------------| |  |-------------------------| 
|__vptr__teacher |--+  | "teacher::~teacher"  | 
|----------------|  |-------------------------| 
teacher t;    | "teacher::show"   | 
          |-------------------------|    

Nói chung, chúng ta không biết chính xác loại các địa chỉ đối tượng ptr ở mỗi lời gọi của chỉ(). Tuy nhiên, chúng ta biết rằng thông qua ptr chúng ta có thể truy cập vào bảng ảo được kết hợp với lớp của đối tượng.

Mặc dù chúng ta không biết mà thể hiện của show() để gọi, chúng ta biết rằng địa chỉ của từng dụ được chứa trong khe 2.

Thông tin này cho phép trình biên dịch để nội bộ chuyển đổi cuộc gọi vào

(*ptr->vptr[ 2 ])(ptr); 

Trong phép chuyển đổi này, vptr đại diện cho con trỏ bảng ảo được tạo bên trong được chèn vào trong mỗi đối tượng lớp và 2 biểu diễn khe được chỉ định của chương trình() trong bảng ảo được liên kết với phân cấp điểm. Điều duy nhất chúng ta cần làm trong thời gian chạy là tính toán kiểu động của ptr (và vtable thích hợp) bằng RTTI.

+0

Ông đã không làm cho destructor ảo của mình mặc dù –

+0

Yep. Tôi nghĩ rằng Zia ur Rahman của aswer sẽ là: "Dear Sir nó không phải là toàn bộ mã, tôi chỉ đăng các mã có vấn đề.";) –

+0

ooooo có sir! bạn đã đúng, tôi chỉ đăng mã có liên quan. bởi vì mọi người ghét đọc mã dài. Và có câu trả lời của bạn là hoàn toàn hữu ích, cảm ơn bạn. –

8

Kể từ show được khai báo virtual trong lớp person, trình biên dịch sẽ không cứng mã gọi phương thức như nó sẽ làm cho một phương pháp không ảo, nó sẽ thay biên dịch một tra cứu trong V-bảng để lấy đúng chức năng.

Vì vậy, ptr->show() sẽ được biên dịch thành ptr->vtable['show']() có nghĩa là "tìm kiếm con trỏ hàm tương ứng với phương pháp show và thực thi nó".

Kể từ lúc chạy, ptr trỏ đến một đối tượng của lớp teacher, khe vtable cho show chứa một con trỏ đến các phương pháp show trong lớp teacher. Đó là lý do tại sao phương thức đúng được thực hiện.

Thực tế, tra cứu trong bảng V không được thực hiện bằng cách sử dụng chuỗi nhưng sử dụng số nhận dạng phương thức số để càng nhanh càng tốt.

4

Ngôn ngữ C++ không xác định việc triển khai đa hình, thậm chí không phải là vtable. Đó là vào các trình biên dịch.
Có thể triển khai có thể thực hiện là Vincent Robert.

3

Tiêu chuẩn không nói gì về cách thực hiện đa hình. Một lớp một vtbl và một đối tượng một vptr là cách phổ biến nhất. Tôi hy vọng mã giả sau sẽ hữu ích.

typedef struct { 
    void (*show)(void* self); 
    // more 

} person_vtbl; 

typedef struct { 
     person_vtbl* vtbl; 
     char   name[20]; 
} person; 

void person_show(void* self) { 
     cout<<"inside ... "<<static_cast<person*>(self)->name; 
} 
// more 

static person_vtbl person_vtbl_ = { &person_show }; // vtbl for person class 

void person_ctor(void* self, char const* name) { 
     person* p = static_cast<person*>(self); 
     strcpy(p->name, name); 
     p->vtbl = &person_vtbl // vptr of person object 
} 

typedef struct { 
    person base; 
    int scale; 
} teacher; 

void teacher_show(void* self) { 
     cout<<"inside the tearch ... "<<static_cast<teacher*>(self)->scale; 
} 
static person_vtbl teacher_vtbl_ = { &teacher_show }; 

void teacher_ctor(void* self, char const* name, int s) { 
     teacher* t = static_cast<teacher*>(self); 
     person_ctor(&t->base, name);  // construct base part 
     t->scale = s;     // construct teacher part 
     t->vtbl = &teacher_vtbl_;  // vptr of teacher object 
} 

// construct teacher : 
// person* ptr = new teacher("Zia", 16); 

teacher* tmp = static_cast<teacher*>(malloc(sizeof *tmp); 
teacher_ctor(tmp, "Zia", 16); // vptr of tmp points to teacher_vtbl_ 
person* ptr = &tmp->base; 

// call virtual function though pointer 
// ptr->show() 

ptr->vptr->show(ptr); // call teacher_show(ptr); 
Các vấn đề liên quan