Bài 12 Các khái niệm nâng cao về Class

 Để một hàm không phải thành viên truy xuất được các thành viên riêng của lớp phải khai báo bằng từ khóa friend.  Cần khai báo prototype của hàm bạn trong phần public của class. Ví dụ class cl { // . public: friend void frnd(cl ob); // . };

pdf21 trang | Chia sẻ: lylyngoc | Lượt xem: 1829 | Lượt tải: 1download
Bạn đang xem trước 20 trang tài liệu Bài 12 Các khái niệm nâng cao về Class, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
1/21 Bài 12 CÁC KHÁI NIỆM NÂNG CAO VỀ CLASS Hàm friend 2/21  Để một hàm không phải thành viên truy xuất được các thành viên riêng của lớp phải khai báo bằng từ khóa friend.  Cần khai báo prototype của hàm bạn trong phần public của class. Ví dụ class cl { // ... public: friend void frnd(cl ob); // ... }; 3/21 class myclass { int a, b; public: myclass(int i, int j) { a=i; b=j; } friend int sum(myclass x); // sum() is a friend of myclass }; int sum(myclass x) { return x.a + x.b; } int main() { myclass n(3, 4); cout << sum(n); return 0; } Ví dụ Quá tải constructor 4/21  Dùng hàm tạo ở những dạng khác.  Để quá tải hàm tạo chỉ việc khai báo dạng mà nó nhận và định nghĩa mỗi hành động liên hệ với những dạng này.  Ví dụ 5/21 #include class timer{ int seconds; public: // seconds specified as a string timer(char *t) { seconds = atoi(t); } // seconds specified as integer timer(int t) { seconds = t; } // time specified in minutes and seconds timer(int min, int sec) { seconds = min*60 + sec; } void run(); } ; void timer::run() { clock_t t1; t1 = clock(); while((clock()/CLOCKS_PER_SEC - t1/CLOCKS_PER_SEC) < seconds); cout << "\a"; // ring the bell } int main() { timer a(10), b("20"), c(1, 10); a.run(); // count 10 seconds b.run(); // count 20 seconds c.run(); // count 1 minute, 10 seconds return 0; } Từ khóa this 6/21  Mỗi khi một hàm thành viên được gọi nó được truyền một con trỏ chỉ đến đối tượng gọi hàm.  Con trỏ this là một tham số không tường minh đối với tất cả các hàm thành viên, vì vậy trong hàm thành viên this có thể được dùng để tham chiếu đến đối tượng gọi nó. class cl { int i; void f() { ... }; // ... }; Bên trong f( ), câu lệnh gán cho i giá trị 10: i = 10; Thực ra câu lệnh trên là viết tắt của : this->i = 10; 7/21 #include using namespace std; class cl { int i; public: void load_i(int val) { this->i = val; } // same as i = val int get_i() { return this->i; } // same as return i } ; int main() { cl o; o.load_i(100); cout << o.get_i(); return 0; } Quá tải toán tử 8/21  C++ cho phép quá tải toán tử liên hệ với các kiểu class.  Quá tải toán tử cho phép định nghĩa ý nghĩa của một toán tử cho một class đặc biệt.  Ví dụ một class định nghĩa một danh sách liên kết có thể dùng toán tử + để thêm một đối tượng vào danh sách.  Quá tải một toán tử chỉ đơn giản là định nghĩa một toán tử mới liên hệ với một class mà không làm thay đổi ý nghĩa gốc của một toán tử. 9/21  Để quá tải một toán tử cần định nghĩa ý nghĩa nào của toán tử liên hệ với class. Tạo một hàm operator, định nghĩa hành vi của toán tử  Dạng tổng quát Kiểu Tên lớp::operator Toán tử(Danh sách tham số) { Hành vi liên hệ với class } 10/21 #include using namespace std; class three_d { int x, y, z; // 3-D coordinates public: three_d() { x = y = z = 0; } three_d(int i, int j, int k) {x = i; y = j; z = k; } three_d operator+(three_d op2); // op1 ẩn three_d operator=(three_d op2); // op1ẩn void show() ; }; // Quá tải +. three_d three_d::operator+(three_d op2) { three_d temp; temp.x = x + op2.x; //x chính là this->x temp.y = y + op2.y; temp.z = z + op2.z; return temp; } // Quá tải phép gán. three_d three_d::operator=(three_d op2) { x = op2.x; y = op2.y; z = op2.z; return *this;//trả về đối tượng được trỏ bởi this } void three_d::show() { cout << x << ", "; cout << y << ", "; cout << z << "\n"; } 11/21 int main() { three_d a(1, 2, 3), b(10, 10, 10), c; a.show(); b.show(); c = a + b; // cộng a với b r c.show(); c = a + b + c; // cộng a, b và c c.show(); c = b = a; // gán liên tiếp c.show(); b.show(); return 0; } Tính thừa kế 12/21  C++ hỗ trợ tính thừa kế bằng cách cho phép một class hợp nhất với class khác trong khai báo.  Khai báo: class Tên class nhận thừa kế : Tên class cho thừa kế { Thân class nhận thừa kế } 13/21 class xe { int banh; int nguoi; public: void set_banh(int num) { banh = num; } int get_banh() { return banh; } void set_ng(int num) { nguoi = num; } int get_ng() { return nguoi; } }; class xe_tai : public xe { int hanghoa; public: void set_hanghoa(int size) { hanghoa = size; } int get_hanghoa() { return hanghoa; } void show(); }; 14/21 #include using namespace std; // Define a base class for vehicles. class road_vehicle { int wheels; int passengers; public: void set_wheels(int num) { wheels = num; } int get_wheels() { return wheels; } void set_pass(int num) { passengers = num; } int get_pass() { return passengers; } }; // Define a truck. class truck : public road_vehicle { int cargo; public: void set_cargo(int size) { cargo = size; } int get_cargo() { return cargo; } void show(); }; enum type {car, van, wagon}; // Define an automoble. class automobile : public road_vehicle { enum type car_type; public: void set_type(type t) { car_type = t; } enum type get_type() { return car_type; } void show(); }; void truck::show() { cout << "wheels: " << get_wheels() << "\n"; cout << "passengers: " << get_pass() << "\n"; cout << "cargo capacity in cubic feet: " << cargo << "\n"; } 15/21 void automobile::show() { cout << "wheels: " << get_wheels() << "\n"; cout << "passengers: " << get_pass() << "\n"; cout << "type: "; switch(get_type()) { case van: cout << "van\n"; break; case car: cout << "car\n"; break; case wagon: cout << "wagon\n"; } } int main() { truck t1, t2; automobile c; t1.set_wheels(18); t1.set_pass(2); t1.set_cargo(3200); t2.set_wheels(6); t2.set_pass(3); t2.set_cargo(1200); t1.show(); cout << "\n"; t2.show(); cout << "\n"; c.set_wheels(4); c.set_pass(6); c.set_type(van); c.show(); return 0; } Dùng thành viên được bảo vệ 16/21  Ngoài private, public, thành viên của class còn được khai báo là protected  Dùng protected có thể tạo các thành viên của class là private đối với class của chúng nhưng vẫn được thừa kế và được truy xuất bởi các lớp nhận thừa kế 17/21 #include using namespace std; class base { protected: int i, j; // private đối với base, nhưng có thể //được truy xuất với derived public: void set(int a, int b) { i = a; j = b; } void show() { cout << i << " " << j << "\n"; } }; class derived : public base { int k; public: // derived có thể truy xuất i và j của base void setk() { k = i*j; } void showk() { cout << k << "\n"; } }; int main() { derived ob; ob.set(2, 3); // derived hiểu và dùng ob.show(); // derived hiểu và dùng ob.setk(); ob.showk(); return 0; } Đa hình 18/21  Đa hình là thuật ngữ mô tả một quá trình trong đó các hiện thực khác nhau của hàm có thể được truy xuất qua cùng một tên.  "Một giao tiếp, Đa phương thức"  Các con trỏ chỉ đến các kiểu thừa kế  Con trỏ lớp cơ sở và con trỏ lớp thừa kế được liên hệ với nhau. 19/21 class B_class { char author[80]; public: void put_author(char *s) { strcpy(author, s); } void show_author() { cout << author << "\n"; } } ; class D_class : public B_class { char title[80]; public: void put_title(char *num) { strcpy(title, num); } void show_title() { cout << "Title: "; cout << title << "\n"; } }; { B_class *p; B_class B_ob; D_class *dp; D_class D_ob; p = &B_ob; // địa chỉ của base // truy xuất B_class qua pointer. p->put_author("Tom Clancy"); // truy xuất D_class qua base pointer. p = &D_ob; p->put_author("William Shakespeare"); // Mỗi author vào một đối tượng thích hợp B_ob.show_author(); D_ob.show_author(); cout << "\n"; dp = &D_ob; dp->put_title("The Tempest"); p->show_author(); // p hoặc dp có thể được //dùng ở đây. dp->show_title( ); return 0; } 20/21  Hàm ảo: Hàm ảo là một hàm được khai báo bằng từ khóa virtual trong một lớp cơ sở và được định nghĩa lại trong một hay nhiều lớp thừa kế. 21/21 class base { public: virtual void who() { // chỉ ra một virtual cout << "Base\n"; } }; class first_d : public base { public: void who() { // định nghĩa lại who() quan hệ //với first_d cout << "First derivation\n"; } }; class second_d : public base { public: void who() { // định nghĩa lại who() quan hệ //second_d cout << "Second derivation\n"; } }; first_d first_obj; second_d second_obj; p = &base_obj; p->who(); // truy xuất who của base p = &first_obj; p->who(); // truy xuất who của first_d p = &second_obj; p->who(); // truy xuất who của second_d return 0; }