Con trỏ hàm ảo và tơng ứng bội

Một phần của tài liệu Lập trình hướng đối tượng (Trang 135 - 138)

3.1. Khái niệm về liên kết tĩnh

- Ta đã biết rằng (quy tắc 2) một con trỏ thuộc lớp cơ sở có thể nhận địa chỉ của bất kỳ đối tợng thuộc các lớp con cháu đợc dẫn xuất từ lớp cơ sở. Tuy nhiên lúc con trỏ này luôn luôn liên kết với các hàm thành phần thuộc lớp cơ sở trong trờng hợp đây là các hàm dịch chuyển. Mối liên kế có tính chất không thay đổi nh vậy gọi là liên kết tĩnh.

3.2. Khái niệm về liên kết động

- C++ đa ra nguyên lý liên kết động cho phép một con trỏ kiểu lớp cơ sở sau khi gán bằng địa chỉ của đối tợng thuộc lớp dẫn xuất nào thì tơng ứng nó sẽ thể liên kết với hàm của chính lớp dẫn xuất đó, mặc dù hàm này là dịch chuyển từ hàm của lớp cơ sở. Cấu trúc cho phép một con trỏ có kiểu cố định nhng có khả năng liên kết với các hàm thành phần dịch chuyển thuộc các lớp khác nhau gọi là liên kết động.

- Cơ chế liên kết tĩnh và liên kết động trong quan hệ kế thừa để phân định việc truy nhập tới các hàm dịch chuyển trong các lớp có quan hệ kế thừa là một trờng hợp cài đặt cụ thể của khái niệm tơng ứng bội trong lập trình h- ớng đối tợng với C++.

- Liên kết động đợc cài đặt bằng cơ chế hàm ảo và nó đợc báo hiệu là hàm ảo bằng cách đặt từ khoá virtual phía trớc khai báo hàm.

Ví dụ 2

#include <iostream.h> #include <conio.h> class A

{ public:

virtual void display(void) {cout<<"Lop A: display()"<<endl;}

void show(void) {cout<<"Lop A: show()"<<endl;} };

class B:public A { public:

void display(void)

{cout<<"Lop B: display()"<<endl;}

void show(void) {cout<<"Lop B: show()"<<endl;} }; int main(){ A a; B b; A *ptr; ptr = &a; ptr->display(); ptr->show(); cout<<endl; ptr= &b; ptr->display(); ptr->show(); cout<<endl; getch(); return 0;}

- Ví dụ trên cho thấy sau khi con trỏ ptr kiểu lớp A, đợc gán bằng địa chỉ của đối tợng b thuộc lớp dẫn xuất B của lớp A thì ptr có thể liên kết với hàm display() của chính lớp B vì hàm display() của lớp A đợc khai báo ảo. Ngợc lại con trỏ ptr vẫn liên kết với hàm show() của lớp cơ

Kết quả

Lop A: display() Lop A: show() Lop B: display() Lop A: show()

sở A chứ không phải của lớp dẫn xuất B vì hàm show() trong lớp cơ sở A không đợc khai báo ảo.

3.3. Các hàm ảo dịch chuyển (Virtual override function)

Khi có một hàm đợc khai báo ảo thì trong lớp dẫn xuất của nó nếu định nghĩa lại hàm này cùng tham số và kiểu tham số thì phải cùng kiểu. Nếu trong lớp dẫn xuất khai báo hàm cùng đặc tính với hàm ảo của lớp cơ sở thì tự khắc nó trở thành hàm ảo mà không phụ thuộc vào hàm đó đợc hoặc không đợc khai báo từ khóa virtual phía trớc, Và, hàm này đợc gọi là hàm ảo dịch chuyển (virtual override

function) từ hàm ảo tơng ứng của lớp cơ sở.

- Trong các ví dụ trên ta sử dụng một biến con trỏ để xác định một đối tợng trong lớp. Trong ví dụ sau đây ta sẽ sử dụng trực tiếp con trỏ đối tợng.

Ví dụ 3 #include <iostream.h> #include <conio.h> #include <stdio.h> class A{ public:

virtual void display() { cout << "\n Class A";} };

class B{ public:

virtual void display() {{ cout<<"\n Class B";} };

void show(A *a) { a->display(); } void main() {

A* a = new A; B* b = new B; a->display(); b->display();

show(b); // goi ham B::display() getch();

}

- Trong ví dụ này, nếu hàm display không đợc khai báo ảo (ở lớp A) thì show(a) sẽ gọi hàm A::display() và

show(b) cũng gọi hàm A::display() vì tham số truyền B* sẽ đợc chuyển kiểu thành A* trớc khi gọi hàm.

Một phần của tài liệu Lập trình hướng đối tượng (Trang 135 - 138)