Bài giảng Lập trình hướng đối tượng - Chương 6: Tính kế thừa
• Giới thiệu tính kế thừa
• Điều khiển truy cập lớp cơ sở
• Sử dụng các thành viên được bảo vệ
• Hàm tạo, hàm hủy và tính kế thừa
• Tính đa kế thừa
• Lớp cơ sở ảo
ãy khảo sát kết quả của chương trình ? #include class A { public: A() { cout << "Constructing A\n"; } ~A() { cout << "Destructing A\n"; } }; class B { public: B() { cout << "Constructing B\n"; } ~B() { cout << "Destructing B\n"; } }; class C : public A, public B { public: C() { cout << "Constructing C\n"; } ~C() { cout << "Destructing C\n"; } }; int main() { C ob; return 0; } Chương 6 Tính kế thừa 195 2. Sử dụng hệ thống thứ bậc lớp sau đây, hãy lập hàm tạo cua lớp C để cho nó khởi đầu k và truyền các đối số cho A() và B() #include class A { int i; public: A(int a) { i = a; } }; class B { int j; public: B(int a) { j = a; } }; class C : public A, public B { int k; public: // Create C() so that it initializes k and passes arguments to both A() and B() ... }; VI/ Lớp cơ sở ảo (virtual base class) Chương 6 Tính kế thừa 196 Khi nhiều lớp cơ sở được kế thừa trực tiếp bởi một lớp dẫn xuất, tồn tại một vấn đề : xuất hiện nhiều bản sao của lớp cơ sở cùng hiện diện trong đối tượng dẫn xuất. Chẳng hạn, xét hệ thống thứ bậc lớp sau Bời vì có hai bản sao của B trong D3, nên một tham chiếu đến một thành viên của B sẽ tham chiếu về B được kế thừa gián tiếp thông qua D1 hay tham chiếu về B được kế thừa gián tiếp thông qua D2 ? Để giải quyết tính không rõ ràng này, C++ có một cơ chế mà nhờ đó chỉ có một bản sao của B ở trong D3. Đặc điểm này được gọi là lớp cơ sở ảo. Có thể ngăn chặn được hai bản sao của lớp cơ sở cùng hiện diện trong đối tượng dẫn xuất bằng cách cho lớp cơ sở đó được kế thừa như virtual bởi bất kỳ các lớp dẫn xuất nào. • Từ khoá virtual đứng trước chỉ định truy cập lớp cơ sở khi nó được kế thừa bởi một lớp dẫn xuất. Ví dụ 6.1 // This program uses a vir #include class base { public: int i; }; // Inherit base as virtual. B B D1 D2 D3tual base class. Chương 6 Tính kế thừa 197 class derived1 : virtual public base { public: int j; }; // Inherit base as virtual, here too. class derived2 : virtual public base { public: int k; }; // Here, derived3 inherits both derived1 and derived2. // However, only one copy of base is present. class derived3 : public derived1, public derived2 { public: int product() { return i * j * k; } }; int main() { derived3 ob; ob.i = 10; // unambiguous because only one copy present ob.j = 3; ob.k = 5; cout << "Product is " << ob.product() << '\n'; return 0; } @ Nếu derived1 và derived2 không kế thừa base như một lớp ảo thì câu lệnh ob.i = 10; sẽ không rõ ràng và sẽ tạo ra lỗi thời gian biên dịch. • Khi một lớp cơ sở được kế thừa như một lớp ảo bởi một lớp dẫn xuất thì lớp cơ sở đó vẫn còn tồn tại trong lớp dẫn xuất . Chương 6 Tính kế thừa 198 Qua ví dụ 6.1 đoạn chương trình sau vẫn hoàn toàn đúng derived1 ob; ob.i = 100; • Sự khác biệt duy nhất giữa lớp cơ sở thường với lớp cơ sở ảo xảy ra khi một đối tượng kế thừa lớp cơ sở hơn một lần. Nếu các lớp cơ sở ảo được sử dụng thì chỉ có một lớp cơ sở hiện diện trong đối tượng. Ngược lại, nhiều bản sao sẽ được tìm thấy. Bài tập VI 1. Trong ví dụ 6.1, bỏ từ khoá virtual và thử biên dịch chương trình. Khảo sát lổi ? 2. Hãy sửa lỗi đoạn chương trình sau // A variation on the vehicle hierarchy. But this program contains an error. Fix it. // Hint : try compiling it as is and observe the error messages. #include // A base class for various types of vehicles. class vehicle { int num_wheels; int range; public: vehicle(int w, int r) { num_wheels = w; range = r; } void showv() { cout << "Wheels: " << num_wheels << '\n'; cout << "Range: " << range << '\n'; } Chương 6 Tính kế thừa 199 }; enum motor {gas, electric, diesel}; class motorized : public vehicle { enum motor mtr; public: motorized(enum motor m, int w, int r) : vehicle(w, r) { mtr = m; } void showm() { cout << "Motor: "; switch(mtr) { case gas : cout << "Gas\n"; break; case electric : cout << "Electric\n"; break; case diesel : cout << "Diesel\n"; break; } } }; class road_use : public vehicle { int passengers; public: road_use(int p, int w, int r) : vehicle(w, r) { passengers = p; } void showr() { cout << "Passengers: " << passengers << '\n'; } }; enum steering { power, rack_pinion, manual }; Chương 6 Tính kế thừa 200 class car : public motorized, public road_use { enum steering strng; public: car(enum steering s, enum motor m, int w, int r, int p) : road_use(p, w, r), motorized(m, w, r), vehicle(w, r) { strng = s; } void show() { showv(); showr(); showm(); cout << "Steering: "; switch(strng) { case power : cout << "Power\n"; break; case rack_pinion : cout << "Rack and Pinion\n"; break; case manual : cout << "Manual\n"; break; } } }; int main() { car c(power, gas, 4, 500, 5); c.show(); return 0; } Bài tập chương 6 Chương 6 Tính kế thừa 201 1. Hãy tạo lớp cơ sở chung building để lưu trữ số tầng nhà mà một toà nhà có số phòng và số tổng diện tích dưới dạng protected. Hãy tạo lớp dẫn xuất house kế thừa building và lưu trữ số phòng ngũ và phòng tắm. Cũng vậy, tạo lớp dẫn xuất office kế thừa public lớp building và lưu trữ số bình cứu hoả và số máy điện thoại. Cả hai lớp dẫn xuất đề có hàm tạo và hàm show. Viết chương trình thực hiện yêu cầu trên ? 2. Cho đoạn chương trình sau, hãy bổ sung các chi tiết theo chỉ dẫn trong các lời chú giải #include class planet { protected: double distance; // miles from the sun int revolve; // in days public: planet(double d, int r) { distance = d; revolve = r; } }; class earth : public planet { double circumference; // circumference of orbit public: // Create earth(double d, int r). Have it pass the distance and days of revolution back // to planet. Have it compute the circumference of the orbit. // (Hint : circumference = 2r*3.1416.) // Create a function called show() that displays the information. }; int main() { earth ob(93000000, 365); ob.show(); return 0; } 3. Cho đoạn chương trình sau, hãy bổ sung để chương trình chạy tốt Chương 6 Tính kế thừa 202 // Overload the +, -, and = relative to coord class. Then, use coord as a base for quad. #include class coord { public: int x, y; // coordinate values coord() { x=0; y=0; } coord(int i, int j) { x=i; y=j; } void get_xy(int &i, int &j) { i=x; j=y; } coord operator+(coord ob2); coord operator-(coord ob2); coord operator=(coord ob2); }; // Overload + relative to coord class. coord coord::operator+(coord ob2) { coord temp; cout << "Using coord operator+()\n"; temp.x = x + ob2.x; temp.y = y + ob2.y; return temp; } // Overload - relative to coord class. coord coord::operator-(coord ob2) { coord temp; cout << "Using coord operator-()\n"; temp.x = x - ob2.x; temp.y = y - ob2.y; return temp; Chương 6 Tính kế thừa 203 } // Overload = relative to coord. coord coord::operator=(coord ob2) { cout << "Using coord operator=()\n"; x = ob2.x; y = ob2.y; return *this; // return the object that is assigned to } class quad : public coord { int quadrant; public: quad() { x = 0; y = 0; quadrant = 0; } quad(int x, int y) : coord(x, y) { if(x>=0 && y>=0) quadrant = 1; else if(x=0) quadrant = 2; else if(x<0 && y<0) quadrant = 3; else quadrant = 4; } void showq() { cout << "Point in Quadrant: " << quadrant << '\n'; } quad operator=(coord ob2); }; quad quad::operator=(coord ob2) { cout << "Using quad operator=()\n"; x = ob2.x; y = ob2.y; Chương 6 Tính kế thừa 204 if(x>=0 && y>=0) quadrant = 1; else if(x=0) quadrant = 2; else if(x<0 && y<0) quadrant = 3; else quadrant = 4; return *this; } int main() { quad o1(10, 10), o2(15, 3), o3; int x, y; o3 = o1 + o2; // add two objects - this calls operator+() o3.get_xy(x, y); o3.showq(); cout << "(o1+o2) X: " << x << ", Y: " << y << "\n"; o3 = o1 - o2; // subtract two objects o3.get_xy(x, y); o3.showq(); cout << "(o1-o2) X: " << x << ", Y: " << y << "\n"; o3 = o1; // assign an object o3.get_xy(x, y); o3.showq(); cout << "(o3=o1) X: " << x << ", Y: " << y << "\n"; return 0; } 4. Hãy sửa đổi chương trình trên sao cho nó sử dụng các hàm toán tử friend ? 5. Hãy tạo một phân cấp lớp để lưu trữ thông tin về máy bay. Hãy bắt đầu bằng một lớp cơ sở tên là airship chứa thông tin về số lượng hành khách tối đa và trọng lượng hàng hoá tối đa (đơn vị tính là pound) mà máy bay có thể chở được. Chương 6 Tính kế thừa 205 Tạo hai lớp dẫn xuất airplane và balloons. Lớp airplane lưu kiểu của động cơ (gồm động cơ cánh quạt và động cơ phản lực), tầm xa (đơn vị tính là mile). Lớp balloon lưu thông tin về loại nhiên liệu sử dụng chi khí cầu (gồm hai loại là hydrogen và helium), độ cao tối đa (đơn vị tính là feed). Viết chương trình minh hoạ hoạt động của chúng.
File đính kèm:
- bai_giang_lap_trinh_huong_doi_tuong_tap_1_chuong_6_tinh_ke_t.pdf