Tải bản đầy đủ

chương 3 lập trình hướng đối tượng

Chöông 4:
SÖÏ KEÁ THÖØA
Nội dung chương 4
1.Giới thiệu về sự kế thừa
1.1.Khái niệm
1.2.Ví dụ
1.3.Ý nghóa
1.4.Chương trình minh họa
2. Kế thừa đơn
2.1.Khái niệm
2.2.Ví dụ
2.3.Phương thức thiết lập và hủy bỏ
2.4.Sự tự động kế thừa các đặc tính lớp cha
2.5.Đònh nghóa lại thao tác ở lớp con
2.6.Ràng buộc ngữ nghóa ở lớp con
Nội dung chương 4 (tt)
2.7.Phạm vi truy xuất
2.7.1.Truy xuất theo chiều dọc
2.7.2.Truy xuất theo chiều ngang
2.8.Con trỏ và sự kế thừa
3.Đa kế thừa

3.1.Khái niệm
3.2.Một số vấn đề
3.3.Ví dụ
3.4.Chương trình minh họa
1.Giới thiệu về sự kế thừa
1.1.Khái niệm về sự kế thừa
-
Sự kế thừa là một đặc điểm của ngôn ngữ dùng để
biểu diễn mối quan hệ đặc biệt giữa các lớp. Các
lớp được trừu tượng hóa và tổ chức thành một sơ đồ
phân cấp lớp.
-
Sự kế thừa là một mức cao hơn của trừu tượng hóa,
cung cấp một cơ chế gom chung các lớp có liên
quan với nhau thành một mức khái quát hóa đặc
trưng cho toàn bộ các lớp nói trên.
-
Các lớp với các đặc điểm tương tự nhau có thể được
tổ chức thành một sơ đồ phân cấp kế thừa. Lớp ở
trên cùng là trừu tượng hóa của toàn bộ các lớp ở
bên dưới nó.
1.1.Khái niệm về sự kế thừa
-
Thừa kế cho phép ta đònh nghóa 1 lớp mới, gọi
là lớp con (subclass) hay lớp dẫn xuất
(derived class) từ một lớp đã có, gọi là lớp
cha (superclass) hay lớp cơ sở (base class).
-
Lớp dẫn xuất sẽ thừa kế các thành phần (dữ liệu,
hàm) của lớp cơ sở, đồng thời thêm vào các thành
phần mới, bao hàm cả việc làm “tốt hơn” hoặc làm
lại những công việc mà trong lớp cơ sở chưa làm tốt
hoặc không còn phù hợp với lớp dẫn xuất
1.1.Khái niệm về sự kế thừa
-
Thừa kế cho phép nhiều lớp có thể dẫn xuất
từ 1 lớp cơ sở
-
Thừa kế cũng cho phép một lớp có thể là dẫn
xuất của nhiều lớp cơ sở


-
Thừa kế không chỉ giới hạn ở 1 mức: Một lớp
dẫn xuất có thể là lớp cơ sở cho các lớp dẫn
xuất khác
1.2.Ví dụ về sự kế thừa
Ví dụ 1:

Xét hai khái niệm người và sinh viên với mối quan
hệ tự nhiên: một 'sinh viên' là một 'người'. Trong C+
+, ta có thể biểu diễn khái niệm trên, một sinh viên
là một người có thêm một số thông tin và một số
thao tác (riêng biệt của sinh viên).

Ta tổ chức lớp sinh viên kế thừa từ lớp người. Lớp
người được gọi là lớp cha (superclass) hay lớp cơ sở
(base class). Lớp sinh viên được gọi là lớp con
(subclass) hay lớp dẫn xuất (derived class).

Ngoài ra, ta có thể tổ chức 2 lớp nam sinh và lớp nữ
sinh là 2 lớp con (lớp dẫn xuất) của lớp sinh viên.
Trường hợp này, lớp sinh viên trở thành lớp cha (lớp
cơ sở) của 2 lớp này
1.2.Ví dụ về sự kế thừa
Hình 4.1: Sơ đồ phân cấp kế thừa
1.2.Ví dụ về sự kế thừa
Ví dụ 2:
Xét bài toán quản lý thư viện, gồm 2 bài toán bộ
phận là quản lý sách và quản lý độc giả. Chúng ta
sẽ xây dựng lớp sách và lớp độc giả. Sau đó dùng
các lớp này làm cơ sở để xây dựng lớp thư viện
-> Lớp thư viện là lớp con (lớp dẫn xuất) của 2
lớp sách và lớp độc giả
1.2.Ví dụ về sự kế thừa
Hình 4.2: Sơ đồ phân cấp kế thừa
1.3.Ý nghóa sự kế thừa

Kế thừa tạo khả năng xây dựng lớp mới từ lớp đã có,
trong đó hàm thành phần được thừa hưởng từ lớp
cha. Trong C++, kế thừa còn đònh nghóa sự tương
thích, nhờ đó ta có cơ chế chuyển kiểu tự động.

Kế thừa vừa có khả năng tạo cơ chế khái quát hoá
vừa có khả năng chuyên biệt hoá.

Kế thừa cho phép tổ chức các lớp chia sẻ mã chương
trình chung nhờ vậy có thể dễ dàng sửa chữa, nâng
cấp hệ thống.
1.4.Chöông trình minh hoïa
class Nguoi {
friend class SinhVien;
char *HoTen;
int NamSinh;
public:
Nguoi(char *ht, int ns):NamSinh(ns)
{HoTen=strdup(ht);}
~Nguoi() {delete [] HoTen;}
void An() const { cout<<HoTen<<" an 3 chen com";}
void Ngu() const { cout<<HoTen<< " ngu ngay 8
tieng";}
void Xuat() const;
friend ostream& operator << (ostream &os, Nguoi&
p);
};
1.4.Chöông trình minh hoïa
class SinhVien : public Nguoi {
char *MaSo;
public:
SinhVien(char *ht, char *ms, int ns) : Nguoi(ht,ns)
{ MaSo = strdup(ms);
}
~SinhVien() {delete [] MaSo;}
void Xuat() const;
};
ostream& operator << (ostream &os, Nguoi& p)
{
return os << "Nguoi, ho ten: " << p.HoTen << " sinh
" << p.NamSinh;
}
1.4.Chöông trình minh hoïa
void Nguoi::Xuat() const {
cout << "Nguoi, ho ten: " << HoTen
<< " sinh " << NamSinh;
}
void SinhVien::Xuat() const {
cout << "Sinh vien, ma so: " << MaSo
<< ", ho ten: " << HoTen;
}
1.4.Chöông trình minh hoïa
void main() {
Nguoi p1("Le Van Nhan",1980);
SinhVien s1("Vo Vien Sinh", "200002541",1984);
cout << ”1.\n";
p1.An(); cout << "\n";
s1.An();cout << "\n";
cout << ”2.\n";
p1.Xuat(); cout << "\n";
s1.Xuat(); cout << "\n";
s1.Nguoi::Xuat(); cout << "\n";
cout << "3.\n";
cout << p1 << "\n";
cout << s1 << "\n";
}
2.Kế thừa đơn
2.1.Khái niệm
-
Kế thừa đơn cho phép một lớp là dẫn xuất của chỉ
duy nhất 1 lớp cơ sở
-
Kế thừa có thể được thực hiện để thể hiện mối quan
hệ 'là một'.
2.2.Ví dụ

Một sinh viên là một người -> Lớp sinh viên là lớp dẫn
xuất của lớp người

Một hình tròn là một hình ellipse-> Lớp ellipse là lớp
dẫn xuất của lớp hình tròn

Một tam giác là một đa giác -> Lớp tam giác là lớp dẫn
xuất của lớp đa giác
2.3.Phương thức thiết lập và hủy
bỏ

Phương thức thiết lập và huỷ bỏ là các hàm thành phần đặc
biệt dùng để tự động khởi động đối tượng khi nó được tạo ra
và tự động dọn dẹp đối tượng khi nó bò hủy đi.

Một đối tượng thuộc lớp con có chứa các thành phần dữ liệu
của các lớp cơ sở. Có thể xem lớp con có các thành phần
ngầm đònh ứng với các lớp cơ sở. Vì vậy khi một đố tượng
thuộc lớp con được tạo ra, các thành phần cơ sở cũng được
tạo ra, nghóa là phương thức thiết lập của các lớp cơ sở phải
được gọi.

Trình biên dòch tự động gọi phương thức thiết lập của các
lớp cơ sở cho các đối tượng (cơ sở) nhúng vào đối tượng
đạng được tạo ra.

Đối với phương thức thiết lập của một lớp con, công việc
đầu tiên là gọi phương thức thiết lập của các lớp cơ sở.
2.3.Phương thức thiết lập và hủy bỏ

Nếu mọi phương thức thiết lập của lớp cơ sở
đều đòi hỏi phải cung cấp tham số thì lớp con
bắt buộc phải có phương thức thiết lập để
cung cấp các tham số đó.
class Diem {
double x,y;
public:
Diem(double x, double y):x(xx),y(yy){}
//...
};
class HinhTron:Diem
{
double r;
public:
void Ve(int color) const;
};
HinhTron t; // SAI
Cung cấp tham số cho phương thức thiết lập của lớp cha

Trong trường hợp đó, lớp con bắt buộc phải có phương
thức thiết lập để cung cấp tham số cho phương thức thiết
lập của lớp cơ sở. Cú pháp để gọi phương thức thiết lập
của lớp cơ sở tương tự như cú pháp thiết lập đối tượng
thành phần, bản thân tên lớp cơ sở được quan điểm như
đối tượng thành phần nhúng vào lớp con.
class HinhTron:Diem {
double r;
public:
HinhTron(double tx, double ty, double
rr):Diem(tx,ty),r(rr){}
void Ve(int color) const;
void TinhTien(double dx, double dy) const;
};
HinhTron t(200,200,50); // Dung
2.3.Phương thức thiết lập và hủy bỏ
class Nguoi {
protected:
char *HoTen;
int NamSinh;
public:
Nguoi(char *ht, int ns):NamSinh(ns) {
HoTen = strdup(ht);
}
//...
};
class SinhVien : public Nguoi {
char *MaSo;
public:
SinhVien(char *ht, char *ms, int ns) : Nguoi(ht,ns)
{ MaSo = strdup(ms);
}
void Xuat() const;
};
2.3.Phương thức thiết lập và hủy
bỏ

Sau khi phương thức thiết lập của các lớp cơ sở
được gọi, mã chương trình trong bản thân phương
thức của lớp con sẽ được thực hiện. Nội dung của
phương thức thiết lập ở lớp con chỉ nên thao tác trên
dữ liệu của riêng lớp con, việc khởi động dữ liệu
thuộc lớp cha do phương thức thiết lập ở lớp cha
đảm nhiệm với các tham số cung cấp bởi lớp con.
class SinhVien : public Nguoi
{
char *MaSo;
public:
SinhVien(char *ht, char *ms, int ns) :
Nguoi(ht,ns) { MaSo = strdup(ms); }
void Xuat() const;
};
2.3.Phương thức thiết lập và hủy bỏ

Ta có thể khởi động các thành phần của lớp
cha bên trong phương thức thiết lập của lớp
con. Trong trường hợp này đối tượng thuộc
lớp cha phải có khả năng tự khởi động:
class Complex {
protected:
double re, im;
public:
Complex(double r = 0, double i = 0):re(r), im(i){}
Complex operator +(Complex b);
Complex operator -(Complex b);
Complex operator *(Complex b);
Complex operator /(Complex b);
double Norm() const {return sqrt(re*re + im*im);}
};
2.3.Phương thức thiết lập và hủy bỏ

Hai cách thiết lập đối tượng thuộc lớp con sau
đây tương đương:
// Cach 1
class Imag: public Complex
{
public:
Imag(double i = 0):Complex(0, i){}
//...
};
// Cach 2
class Imag: public Complex
{
public:
Imag(double i = 0){re = 0; im = i;){}
//...
};
2.3.Phương thức thiết lập và hủy
bỏ

Cách tiếp cận thứ hai tốt hơn
class Nguoi {
protected:
char *HoTen;
int NamSinh;
public:
Nguoi(char *ht = "Ng Van A", int ns = 1980)
:NamSinh(ns) {HoTen = strdup(ht);}
~Nguoi() {delete [] HoTen;}
//...
};

Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay

×