Tải bản đầy đủ (.ppt) (25 trang)

Phần 2: Ngôn ngữ lập trình C++ - Chương 4: Kế thừa ppt

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (175.59 KB, 25 trang )

Ch ng 4: K th aươ ế ừ
Phần 2: Ngôn ngữ lập trình C++
Các nội dung chính

Các khái niệm cơ bản

Phân loại kế thừa

Kế thừa đơn

Tính đa hình

Lớp trừu tượng

Kế thừa bội
Các khái niệm cơ bản

Kế thừa (inheritance):
Lớp B kế thừa lớp A, tức là B sẽ có thể tái sử
dụng các thành phần dữ liệu và các thao tác
trong A
A
B
Lớp cha (lớp cơ sở)
Lớp con (lớp dẫn xuất)
Ví dụ về sự kế thừa
Lớp Số
+, -, *, /
<,>,==,…
Giá trị
Lớp Số Thực


+, -, *, /
<,>,==,…
Giá trị thực
Lớp Số Nguyên
+, -, *, /
<,>,==,…
Giá trị nguyên
Lớp Phân Số
+, -, *, /
<,>,==,…
Giá trị mẫu số
Lớp Số Phức
+, -, *, /
<,>,==,…
Giá trị phức
Phân loại kế thừa

Có hai cách phân loại

Theo mức độ kế thừa: có 2 mức

Public: bảo toàn mức độ che dấu của các thành phần của
lớp cơ sở trong lớp dẫn xuất

Private: đưa các mức che dấu của các thành phần trong lớp
cơ sở lên mức private trong lớp dẫn xuất

Theo số lượng lớp cơ sở: có 2 loại

Kế thừa đơn


Kế thừa bội
Cú pháp khai báo kế thừa

Kế thừa đơn

Trong đó E có thể
là:

public

private

Kế thừa bội
class B: <E> A {
//Đ/n phần thân của lớp dẫn xuất
};
class C: <E
A
> A, <E
B
> B {
//Đ/n phần thân của lớp dẫn xuất
};
Kế thừa đơn

Chương trình 4.1: xây dựng hai lớp số Real và
Complex, trong đó lớp Complex kế thừa lớp
Real
class Real {

protected:
float r;
public:
Real(float a=0){
r = a;
}
//tiếp ở hình bên
};
class Real {
//tiếp từ hình bên
Real Add(Real x){
Real z;
z.r = x.r +r;
return z;
}
void Print(){
cout<<r;
}
};
Chương trình 4.1 (tiếp)
class Complex: public Real {
float i; //Phan ao
public:
Complex(float rp=0, float
ip=0):Real(rp){
i=ip;
}
//tiếp ở hình bên
};
class Complex: public Real {

//tiếp từ hình bên
Complex Add(Complex x)
{
Complex a;
a.r = x.r +r;
a.i = x.i +i;
return a;
}
void Print(){
Real::Print();
cout<<"+j"<<i;
}
};
Chương trình 4.1 (tiếp và hết)
main(){
Real x, y(10.5),z(25.5);
x = y.Add(z);
cout<<"x="; x.Print();
cout<<endl;

Complex c, d(5,6), e(6,9);
c = d.Add(e);
cout<<"c="; c.Print();
cout<<endl;

return system("PAUSE"),EXIT_SUCCESS;
}
Kết quả chạy
Tính đa hình và hàm ảo


Khái niệm đa hình:

Ta thấy trong chương trình ở trên, trong hàm main
có các đối tượng của cả lớp Real và Complex. Các
đối tượng này đều có hàm thành viên Print() không
có tham số để in ra nội dung của từng đối tượng. Do
đó, khi hàm main gửi thông báo Print cho các đối
tượng, yêu cầu hiển thị nội dung của chúng thì các
đối tượng đều gọi hàm Print để in nội dung của
chúng ra màn hình. Do các đối tượng có các nội
dung khác nhau nên các nội dung in ra cũng khác
nhau. Đây được gọi là sự đa hình, và hàm thành viên
giống nhau cho nhiều lớp khác nhau được gọi là hàm
đa hình.
Tính đa hình
main()
:a Real
Print()
:a Complex
Print()
Print
Print
Vấn đề với tính đa hình
main(){
Real x(10.5);
cout<<"x="; x.Print(); cout<<endl;

Complex c(6,9);
cout<<"c="; c.Print(); cout<<endl;
Real *pr = &x;

cout<<"x=";pr->Print();cout<<endl;
pr=&c;
cout<<"c=";pr->Print();cout<<endl; //Vấn đề ở đây
return system("PAUSE"),EXIT_SUCCESS;
}
Kết quả chạy
Vấn đề với tính đa hình

Vấn đề nằm ở dòng in ra c = 6, tức là chỉ in ra
phần thực của c, mặc dù con trỏ pr đã trỏ vào c

Nguyên nhân:

Do bên trong mỗi đối tượng thuộc lớp Complex có 2
hàm Print(), một kế thừa từ lớp Real, và một được
định nghĩa lại trong lớp Complex, nên khi gọi pr-
>Print(), hệ thống đã liên kết và gọi đến hàm Print
của lớp Real, vì nó chỉ xét kiểu của con trỏ pr là kiểu
Real, chứ không xét đến bản thân kiểu của đối tượng
mà pr đang trỏ đến. Đây là hình thức liên kết sớm
(early binding), được thực hiện vào lúc dịch chương
trình
Giải pháp cho vấn đề đa hình

Sử dụng hàm ảo
(virtual)

Thêm từ khóa virtual
vào khai báo của hàm
Print trong lớp Real


Khi đó hàm Print trong
lớp Complex cũng là
hàm virtual, mặc dù ta
không cần lặp lại từ
khóa này trong đ/n của
hàm này
class Real {
//tiếp từ hình bên
Real Add(Real x){
Real z;
z.r = x.r +r;
return z;
}
virtual void Print(){
cout<<r;
}
};
Kết quả chạy lại
Hàm ảo và cơ chế liên kết muộn

Cơ chế liên kết muộn (late binding)

Khi gặp hàm ảo, thì hệ thống không thực hiện liên
kết sớm khi dịch chương trình, mà chờ đến khi chạy
chương trình, sau khi xác định rõ kiểu của đối tượng
mà thi hành hàm đó, thì việc liên kết mới được thực
hiện, nhằm tìm đúng loại hàm cần thiết để thực hiện.
Lớp trừu tượng và hàm ảo thuần túy


Hàm ảo thuần túy (pure virtual function):

Là hàm ảo không có phần định nghĩa (không
có phần thân hàm)

Lớp trừu tượng (abstract class):

Là lớp có ít nhất một hàm thành viên là ảo
thuần túy
Ví dụ
//Đ/n lớp trừu tượng
class Number {
//Khai báo hàm ảo thuần túy
public:
virtual void Print()=0;
};
class Integer: public Number {
public:
void Print();
};
class Real: public Number {
public:
void Print();
};
class Integer
Print()
class Real
Print()
Abs class
Number

virtual Print()=0
Lớp trừu tượng

Một số quy tắc:

Lớp trừu tượng không có đối tượng, nó được dùng
để khái quát các thành phần chung nhất của các lớp

Có thể khai báo con trỏ kiểu lớp trừu tượng

Một hàm ảo thuần túy trong lớp trừu tượng cần phải
được định nghĩa lại trong lớp dẫn xuất; hoặc tiếp tục
là hàm ảo trong lớp đó, khi đó lớp dẫn xuất này lại là
trừu tượng.
Kế thừa bội

Bài tập về nhà nghiên cứu
Tóm tắt

Khái niệm cơ bản về kế thừa

Cách phân loại kế thừa

Tính đa hình và cách cài đặt

Sự khác nhau giữa hàm ảo và hàm thông thường

Lớp trừu tượng và hàm ảo thuần túy

Kế thừa bội

Bài tập

Bài 1: Xây dựng cây các lớp số: gồm các lớp Number,
Integer, Fraction, Real, Complex có nút gốc là lớp
Number. Mỗi lớp gồm các thao tác:

Số học: +,-,*,/

So sánh: <,>,==

Phép xuất ra màn hình <<

Bài 2: Xây dựng một cây các lớp hình: gồm các lớp
Shape, Rectangle, Square, Triangle, Quadrangle. Mỗi
lớp gồm các thao tác:


Thank you!

×