SlideShare a Scribd company logo
1 of 39
Download to read offline
Lập trình hướng đối
tượng C++
Giảng viên giảng dạy: Nguyễn
Hữu Vân Long
1
Chương 8
Thừa kế
(Inheritance)
2
3
BM MTT&TT 4
 Giới thiệu
 Một số khái niệm
 Thừa kế đơn
 Hàm xây dựng
 Hàm xây dựng sao chép
 Hàm hủy
 Tái định nghĩa...
 Liên kết tĩnh và liên kết động
 Đa thừa kế
Nội dung bài giảng
BM MTT&TT 5
 Thừa kế
 Là một trong những đặc tính mạnh nhất của OOP.
 Là quá trình tạo ra các lớp mới từ những lớp đã có.
 Về mặt ngữ nghĩa, lớp mới phải “là” lớp đã có với một vài
đặc điểm hoặc tính năng mới.
 Mục đích
 Xây dựng lớp mới từ những lớp đã có.
 Dùng lại mã (code reusability)
 Sử dụng sự tương tự và sự khác nhau để mô hình hóa các
lớp đối tượng có liên quan với nhau.
 Là một cách để tổ chức thông tin.
Giới thiệu
BM MTT&TT 6
Xây dựng lớp mới từ lớp đã có
void Thisinh2008::hienthi()
{
Thisinh::hienthi();
cout << "Noi thi: ";
cout << noithi;
}
void Thisinh2008::nhap()
{
Thisinh::nhap();
cout << "Nhap noi thi: ";
cin >> noithi;
}
Tận dụng lại các đoạn
mã đã viết sẵn
BM MTT&TT 7
 Các loại hình dạng đều có một số thuộc tính, phương thức
giống nhau. Các loài bò sát, động vật có vú, cá, … đều là
động vật, đều cùng một loài.
Sự tương tự và sự khác nhau
BM MTT&TT 8
 Lớp cha và lớp con
 Lớp được thừa kế: Lớp cha (parent class), lớp cơ sở (base
class).
 Lớp thừa kế: Lớp con (child class), lớp dẫn xuất (derived
class).
 Các loại thừa kế
 Thừa kế đơn: Lớp con thừa kế từ một lớp cha.
 Đa thừa kế: Lớp con thừa kế từ nhiều lớp cha.
Một số khái niệm
BM MTT&TT 9
 Một số đặc điểm
 Quan hệ giữa lớp con và lớp cha là quan hệ “là”.
 Lớp con, mặc nhiên sẽ có tất cả các thành phần của lớp
cha. Tuy nhiên, nó chỉ truy xuất được các thành phần
public hoặc protected.
 Lớp con được tạo ra bằng cách
 Thêm vào các thuộc tính mới.
 Thêm vào các phương thức mới.
 Thể hiện hóa một số thuộc tính của lớp cha.
 Đổi kiểu dữ liệu của thuộc tính của lớp cha.
 Tái định nghĩa, chồng các phương thức của lớp cha.
Một số khái niệm
BM MTT&TT 10
 Lớp con chỉ thừa kế từ một lớp cha.
 Cú pháp:



 Dạng thừa kế: dùng để chỉ định các thành phần của lớp
cha sẽ xuất hiện trong lớp con với thuộc tính truy xuất gì.
Thừa kế đơn
class <tên lớp con> : [dạng thừa kế] <tên lớp cha> {
//các thành ph n (thu c tính/ph ng th c) c a l p conầ ộ ươ ứ ủ ớ
...
};
Dạng t.kế
Lớp cha
public protected
private
(mặc nhiên)
public public protected private
protected protected protected private
private private private private
BM MTT&TT 11
 Dạng thừa kế
Thừa kế đơn
class A {
int x;
void Fx ();
public:
int y;
void Fy ();
protected:
int z;
void Fz ();
};
class B : A { // Thừa kế dạng private
…….
};
class C : private A { // A là lớp cơ sở riêng của
C
………
};
class D : public A { // A là lớp cơ sở chung
của D
………
};
class E : protected A { // A: lớp cơ sở được
bảo vệ
……….
};
BM MTT&TT 12
 Chú ý: L p con th a k  (có) t t c  các thành ph n c a l p cha nh ng ch  ớ ừ ế ấ ả ầ ủ ớ ư ỉ
đ c truy xu t các thành ph n ượ ấ ầ public ho c ặ protected
class Diem {
int x, y;
public:
void ganDiem(int h, int t) {
x = h; y = t;
}
void hienthi() {
cout << "(" << x
<< ", "<< y << ")";
}
void doiDiem(int dx, int dy) {
x += dx; y += dy;
}
...
};
class Diemmau : public Diem {
int mau; //b sung thêm thu c tínhổ ộ
“màu”
public:
void ganDM(int h, int t, int m) {
ganDiem(h, t); mau = m;
}
void hienthiDM() {
hienthi();
cout << ", mau: " << mau;
}
};
void main() {
Diemmau a;
a.ganDM(0, 0, 7);
a.hienthiDM();
cout << endl;
a.doiDiem(2, 1);
a.hienthiDM();
}
a
x, y, mau
ganDiem()
hienthi()
doiDiem()
ganDM()
hienthiDM()
Thừa kế đơn
 Thứ tự khởi tạo: Thành phần lớp cha => Thành phần lớp
con => Hàm xây dựng của lớp cha sẽ được gọi trước,
sau đó là hàm xây dựng của lớp con.
 Khi gọi hàm xây dựng: phải gọi hàm xây dựng của lớp
cha trước khi khởi tạo các dữ liệu của lớp con.
 Nếu hàm XD của lớp con không gọi hàm XD lớp cha một
cách tường minh thì hàm xây dựng không đối số sẽ được
gọi.
Thừa kế đơn - Hàm xây dựng
 Ví dụ
Thừa kế đơn - Hàm xây dựng
int main()
{
B objB;
return 0;
}
class A {
public:
A() {
cout << "A's constructorn";
}
};
class B : public A {
public:
B() {
cout << "B's constructorn";
}
};
 Cú pháp gọi hàm xây dựng của lớp cha:
Thừa kế đơn - Hàm xây dựng
<phần khai báo hàm XD lớp con> : <tên lớp cha>([DS đối số])
{
//thân hàm XD c a l p conủ ớ
}
Tùy vào danh sách đối số mà hàm
xây dựng tương ứng của lớp cha
sẽ được gọi
class X {
int a;
public:
//X’s constructors
X() { a = 0; }
X(int aa) { a = aa; }
//. . .
};
class Y : public X {
int b;
public:
//Y’s constructors
Y() : X() { b = 0; }
Y(int aa, int bb) : X(aa) {
b = bb;
}
//. . .
};
Gọi hàm XD của lớp cha
Thừa kế đơn - Hàm xây dựng
mau:
void main()
{
Diemmau a;
Diemmau b(1, 1, 3);
}
x:
y:
0
0
0
a
//th a k t l p Diemừ ế ừ ớ
Diem()
mau = 0;
mau:
x:
y:
1
1
3
b
//th a k t l p Diemừ ế ừ ớ
Diem(1, 1)
mau = 3;
class Diem {
int x, y;
public:
Diem() { x = y = 0; }
Diem(int h, int t) {
x = h; y = t;
}
};
class Diemmau : public Diem {
int mau;
public:
Diemmau() : Diem() { mau = 0; }
Diemmau(int h, int t, int m)
:Diem(h, t) {
mau = m;
}
}; Gọi hàm XD của lớp cha
 Hàm xây dựng sao chép
 Bên trong mỗi đối tượng của lớp con, luôn có các thành
phần dữ liệu của lớp cha trong hàm XDSC của lớp con
phải gọi hàm XDSC của lớp cha để đảm bảo các dữ liệu
này cũng được sao chép.
 Cú pháp gọi hàm XDSC của lớp cha
Thừa kế đơn - Hàm XD sao chép
<tên lớp con>(const <tên lớp con>& obj) : <tên lớp cha>(obj)
{
//thân hàm XDSC c a l p conủ ớ
}
Prototype hàm XDSC lớp con Gọi hàm XDSC lớp cha
Các thành phần dữ liệu của lớp cha bên trong ĐT obj
sẽ được sử dụng để sao chép cho các t.phần dữ liệu
của lớp cha của ĐT mới.
18
//constructors
Emp::Emp () : Person() {
dept = new char[30];
strcpy(dept, "");
salary = 0.0;
}
Emp::Emp (char* n, char* d,
float s) : Person(n) {
dept = strdup(d);
salary = s;
}
//copy constructor
Emp::Emp(const Emp& e)
:Person(e) {
dept = strdup(e.dept);
salary = e.salary;
}
//Constructors
Person::Person() {
name = new char[50];
strcpy(name, "");
}
Person::Person(char* n) {
name = strdup(name);
}
//copy constructor
Person::Person(const Person& p)
{
name = strdup(p.name);
} Gọi hàm XDSC cho lớp cha
Thừa kế đơn - Hàm XD sao chép
 Thuộc tính của lớp con trùng tên thuộc tính của lớp cha.
 Trong lớp con, nếu ta truy xuất đến dữ liệu trùng tên đó thì
sẽ truy xuất đến dữ liệu của lớp con.
 Truy xuất dữ liệu lớp cha : <Tên lớp cha>::<dữ liệu>
Thừa kế đơn - Tái ĐN dữ liệu TV
class LopCha {
public:
int a;
LopCha()
{ a= 0; }
};
class LopCon : public LopCha {
public:
int a;
LopCon();
void Hien();
};
LopCon::LopCon() : LopCha()
{ a = 1; }
void LopCon::Hien()
{ cout << a << LopCha::a; }
void main() {
LopCon x;
x.Hien();
cout << x.a
<< x.LopCha::a;
}
 Hàm thành viên của lớp con trùng tên với hàm thành viên
của lớp cha.
 Gọi hàm trùng tên => gọi hàm của lớp con.
 Gọi hàm của lớp cha : <Tên lớp cha>::<tên hàm>(…)
Thừa kế đơn - Tái ĐN dữ liệu TV
class Diem {
int x, y;
public:
...
void Hien()
{ cout<<“(”<<x<<“,”<<y<<“)”;}
};
class DiemMau : public Diem {
int mau;
public:
void Hien();
...
};
void DiemMau :: Hien()
{ Diem::Hien();
cout<<“ mau ”<<mau;
}
void main() {
DiemMau a(2,5,4);
a.Hien();
a.DiemMau::Hien();
DiemMau b=a;
b.Diem::Hien();
}
 Cũng tương tự như hàm XDSC, hàm tái định nghĩa toán tử
gán ‘=’ của lớp con cũng phải gọi đến hàm tái định nghĩa
tác tử ở lớp cha để thực hiện sự sao chép cho các thành
phần của lớp cha.
Thừa kế đơn - Tái ĐN phép gán
//assignment operator overloading
Person& Person::operator= (const Person& p) {
delete[] name;
name = strdup(p.name);
return *this;
}
Emp& Emp::operator= (const Emp& e) {
Person::operator=(e);
delete[] dept;
dept = strdup(e.dept);
salary = e.salary;
}
Gọi hàm tái ĐN phép gán
cho lớp cha
 Hủy đối tượng, hàm hủy:
 Khi một đối tượng thuộc lớp con bị hủy, hàm hủy của lớp
cha sẽ tự động được gọi (nếu có), ngay cả trong trường
hợp lớp con không có hàm hủy.
 Hàm hủy của lớp con (nếu có) không cần gọi đến
hàm hủy của lớp cha.
 Thứ tự: hàm hủy lớp con => hàm hủy lớp cha.
Thừa kế đơn - Hàm hủy
class Person {
char* name;
public:
//. . .
~Person() {delete[] name; }
//. . .
};
class Emp {
char* dept;
float salary;
public:
//. . .
~Emp() {delete[] dept; }
//. . .
};
Thừa kế đơn - Hàm hủy
class X {
int* x_data; int x_size;
public:
//...constructors + member functions
//destructor
~X() {
cout << "X's destructorn";
delete[] x_data;
}
};
class X : public Y {
int* x_data; int x_size;
public:
//...constructors + member functions
//destructor
~Y() {
cout << “Y's destructorn";
delete[] y_data;
}
};
int main()
{
Y yObj;
return 0;
}
Trường hợp Y không có hàm hủy
 Sự tương thích giữa đối tượng của lớp con và đối
tượng của lớp cha
Liên kết tĩnh và liên kết động
•
Một đối tượng thuộc lớp
con có thể được gán cho
một đối tượng thuộc lớp
cha.
•
Một con trỏ thuộc lớp
cha có thể trỏ đến một
đối tượng thuộc lớp con.
•
Không có chiều ngược
lại.
24
void main() {
LopCha a;
LopCon b;
a = b;
b = a; // Sai
LopCha *pa;
pa = &a;
LopCon *pb;
pb = &b;
pa = &b;
pb = &a; // Sai
}
Con trỏ của lớp cha
có thể trỏ đến
đối tượng
của lớp con
Có thể gán Cha = Con
Hổn
 Liên kết tĩnh
 Sự liên kết giữa con trỏ đối tượng và hàm thành viên
được thực hiện lúc biên dịch => Con trỏ thuộc lớp
nào sẽ gọi hàm thành viên của lớp đó.
Liên kết tĩnh và liên kết động
class LopCha {
...
public:
…
void HamThanhVien() {
cout<<“Ham cua Lop Cha”;
}
};
class LopCon : public LopCha {
...
public:
…
void HamThanhVien() {
cout<<“Ham cua Lop Con”;
}
};
void main() {
LopCha a;
LopCha *pa=&a;
pa->HamThanhVien(); //Lớp cha
LopCon b;
LopCon *pb=&b;
pb->HamThanhVien(); //Lớp con
pa= &b;
pa->HamThanhVien(); //Lớp cha
pb= &a; //Báo lỗi
}
26
bObj
draw()
dObj
draw()
Base
draw()
Base* bp
Base bObj, *bp;
Derived dObj;
bp = &bObj;
bp->draw();
//G i hàm draw() c a l p Baseọ ủ ớ
bp = &dObj;
bp->draw();
//G i hàm draw() c a l p Baseọ ủ ớ
Liên kết tĩnh và liên kết động
 Liên kết động
 Sự liên kết giữa con trỏ đối
tượng và hàm thành viên
được thực hiện lúc thực thi
chương trình, con trỏ đang
trỏ tới đối tượng thuộc lớp
nào thì hàm thành viên của
lớp đó được gọi.
 Chỉ thực hiện được khi hàm
thành viên được khai báo là
hàm ảo (virtual function)
trong lớp cha.
 Thể hiện cho tính đa hình của
lập trình Hướng đối tượng:
cùng một thông điệp nhưng
có thể được ứng xử khác
nhau tùy vào từng “hoàn
cảnh” cụ thể.
Liên kết tĩnh và liên kết động
class LopCha {
...
public:
…
virtual void HamAo() {
cout<<“Ham cua Lop Cha”;
}
};
class LopCon : public LopCha {
...
public:
…
void HamAo() {
cout<<“Ham cua Lop Con”;
}
};
void main() {
LopCha a;
LopCha *pa=&a;
pa->HamAo(); //Lớp cha
LopCon b;
LopCon *pb=&b;
pb->HamAo(); //Lớp con
pa= &b;
pa->HamAo(); //Hàm lớp con
pb= &a; //Báo lỗi
}
 Hàm ảo
 Cú pháp: khai báo thêm từ khóa virtual trước hàm.
 Dùng chung với tính liên kết động => tính đa hình
 Hàm hoàn toàn ảo
 Là hàm ảo chỉ có khai báo, không có định nghĩa
 Cú pháp: chỉ khai báo tên trong lớp cha và gán=0.
 Hàm hoàn toàn ảo phải định nghĩa lại trong lớp con.
Liên kết tĩnh và liên kết động
class Base {
public:
virtual void draw() { ... }
};
class Base {
public:
virtual void draw() = 0;
};
class Base {
public:
virtual void draw() = 0;
};
Liên kết tĩnh và liên kết động
class Base {
public:
void virtual draw() { ... }
};
class Derived : public Base {
public:
void draw() { . . .}
};
Base bObj, *bp;
Derived dObj;
bp = &bObj;
bp->draw(); //Goi ham draw() cua lop Base
bp = &dObj;
bp->draw(); //Goi ham draw() cua lop Derived
bObj
draw()
dObj
draw()
Base
draw()
Base* bp
Liên kết tĩnh và liên kết động
class Shape {
//. . .
public:
virtual void draw() = 0;
};
class Circle : public Shape {
//. . .
public:
void draw() {
cout << "Circle's draw()n";
}
};
class Triangle : public Shape {
//. . .
public:
void draw() {
cout << "Triangle's draw(n)";
}
};
class Rectangle : public Shape {
//. . .
public:
void draw() {
cout << "Rectangle's draw()n";
}
};
void main() {
Shape* shapeArr[4];
shapeArr[0] = new Circle();
shapeArr[1] = new Triangle();
shapeArr[2] = new Circle();
shapeArr[3] = new Rectangle();
for (int i=0; i<4; i++)
shapeArr[i]->draw();
}
 Hàm hủy
 Hàm hủy của lớp cơ sở nên được khai báo là hàm ảo.
 Lý do: Sử dụng tính liên kết động để hủy đối tượng.
 Lớp ảo
 Là lớp có chứa ít nhất một hàm ảo.
 Không thể tạo đối tượng thuộc lớp ảo.
 Tuy nhiên, có thể tạo con trỏ thuộc lớp ảo.
 Ví dụ: Lớp Shape trong VD trước là lớp ảo.
Liên kết tĩnh và liên kết động
 Lớp con thừa kế từ nhiều hơn một lớp cha.
 Cú pháp:
Đa thừa kế
class <tên lớp con> : {[dạng thừa kế] <tên lớp cha>} {,… n}
{
//các thành ph n (thu c tính/ph ng th c) c a l p conầ ộ ươ ứ ủ ớ
...
};
class Z : public X, public Y
{
//...
};
class X {
//...
};
class Y {
//...
};
 Ưu điểm
 Tận dụng được những thành phần đã có sẵn của lớp cha:
 Dữ liệu thành viên
 Hàm thành viên
 Thuận lợi khi sử dụng kết hợp với hàm ảo.
 Vấn đề cần lưu ý khi sử dụng thừa kế bội
 Cạnh tranh trong thừa kế bội.
 Thiết kế sơ đồ thừa kế phải đúng ý nghĩa.
 Nên hạn chế và cẩn thận khi sử dụng thừa kế bội.
Đa thừa kế
SinhViên
SinhViênTạiChức
– mã số
NhânViên
– mã số
Dữ liệu của SinhViên
Dữ liệu của NhânViên
Dữ liệu của SinhViênTạiChức
Tạo ra
đối
tượng
class XeDien {
int loaibinhdien;
int thoigian;
float tocdo;
public:
XeDien() { … }
XeDien(int b, int tg, float td) { … }
…
};
class XeDapDien : public XeDap, public XeDien {
…
public:
XeDapDien();
XeDapDien( char*, char*, int , int , int , float );
…
};
XeDapDien::XeDapDien () : XeDap(), XeDien() { … }
XeDapDien::XeDapDien ( char* a, char* b, int c, int d, int e, float f )
: XeDap(a, b, c), XeDien(d,e,f) { … }
…
class XeDap {
char loai[10];
char* mau;
int chieucao;
public:
XeDap() { … }
XeDap(char* l, char* m, int c) { … }
…
};
Khai báo lớp trong
thừa kế bội
Gọi hàm xây dựng
của các lớp cha
Đa thừa kế
35
class Student { //educational background
char school[30]; //name of school
char degree[20]; //highest degree
public:
void getedu() {
cout << "School: ";
cin >> school;
cout << "Highest degree: ";
cin >> degree;
}
void putedu() {
cout << "School: " << school;
cout << “Degree: " << degree;
}
};
class employee {
char name[40]; //employee name
unsigned long ID; //employee ID
public:
void getdata() {
cout << "Name: "; cin >> name;
cout << "ID: "; cin >> number; }
void putdata() {
cout << "Name: " << name;
cout << "ID: " << number;
}
};
class manager : employee, student {
char title[20]; //”vice-president” etc.
double dues; //golf club dues
public:
void getdata() {
employee::getdata();
cout << "Title: "; cin >> title;
cout << "Club dues: "; cin >> dues;
student::getedu();
}
void putdata() {
employee::putdata();
cout << "nTitle: " << title;
cout << "nClub dues: " << dues;
student::putedu();
}
};
Đa thừa kế
 Thứ tự khởi tạo: giống như trong Thừa kế đơn, các thành
phần dữ liệu của lớp cha sẽ được khởi tạo trước, sau đó
tới lớp con.
 Hàm XD/XDSC của lớp con cần gọi đến hàm XD/XDSC thích
hợp ở lớp cha.
 Cú pháp: tương tự trong Thừa kế đơn.
Đa thừa kế - Khởi tạo
class X {
// data
public:
//methods
};
class Y {
// data
public:
//methods
};
class Z : public X, private Y {
//data
public:
//constructor
Z(...) : X(...), Y(...) {
//...
}
//copy constructor
Z(const Z& obj) : X(obj), Y(obj) {
//...
}
};
 Trong Đa thừa kế, ta thường gặp phải một số vấn đề
 Sự trùng lặp dữ liệu của lớp cơ sở chung trong lớp kế thừa.
 Xung đột tên của các hàm thành viên hoặc dữ liệu thành
viên giữa các lớp cơ sở.
Đa thừa kế - Một số vấn đề
SaleManger
SalePerson Manager
EmployeeEmployee
 Cách giải quyết các vấn đề trên
 Sự trùng lặp dữ liệu của lớp cơ sở chung: Dùng lớp cơ sở
ảo.
Đa thừa kế - Một số vấn đề
class A {
// . . .
};
class X : public A {
// . . .
};
class Y : public A {
// . . .
};
class X : virtual public A {
// . . .
};
class Y : virtual public A {
// . . .
};
class Z : public X, public Y {
//. . .
};
Z
X Y
AA
Z
X Y
A
(Dùng chung bởi X và Y)
 Cách giải quyết các vấn đề trên
 Dùng tên lớp cơ sở một cách tường minh trong truy xuất
các thành phần trùng tên trong lớp cơ sở.
Đa thừa kế - Một số vấn đề
class X {
public:
void print()
{ cout << "X's print()"; }
};
class Y : virtual public X {
public:
void print()
{ cout << "Y's print"; }
};
class T : virtual public X {
public:
void print()
{ cout << "T's print"; }
};
class U : public Y, public T {
public:
void print() {
cout << "U's print";
}
};
int main()
{
U u;
u.print(); // U's print invoked
u.X::print(); // X's print invoked
u.Y::print(); // Y's print invoked
u.T::print(); // T's print invoked
return 0;
}

More Related Content

What's hot

Pplthdt c00 gioi_thieumonhoc_v13.09a
Pplthdt c00 gioi_thieumonhoc_v13.09aPplthdt c00 gioi_thieumonhoc_v13.09a
Pplthdt c00 gioi_thieumonhoc_v13.09aPix Nhox
 
Jniについて
JniについてJniについて
JniについてChu Chu
 
Pplthdt c02 lop_doi_tuong_v13.09a
Pplthdt c02 lop_doi_tuong_v13.09aPplthdt c02 lop_doi_tuong_v13.09a
Pplthdt c02 lop_doi_tuong_v13.09aPix Nhox
 
179887496 sdc1-bai tap-javacanban-5
179887496 sdc1-bai tap-javacanban-5179887496 sdc1-bai tap-javacanban-5
179887496 sdc1-bai tap-javacanban-5le dai
 
Bai06 mot sokythuattrongkethua
Bai06 mot sokythuattrongkethuaBai06 mot sokythuattrongkethua
Bai06 mot sokythuattrongkethuaNhuận Lê Văn
 
Oop unit 04 các kỹ thuật xây dựng lớp
Oop unit 04 các kỹ thuật xây dựng lớpOop unit 04 các kỹ thuật xây dựng lớp
Oop unit 04 các kỹ thuật xây dựng lớpTráng Hà Viết
 

What's hot (19)

Chuong 6
Chuong 6Chuong 6
Chuong 6
 
Chuong 4
Chuong 4Chuong 4
Chuong 4
 
Bai05 ket tapvakethua
Bai05 ket tapvakethuaBai05 ket tapvakethua
Bai05 ket tapvakethua
 
Pplthdt c00 gioi_thieumonhoc_v13.09a
Pplthdt c00 gioi_thieumonhoc_v13.09aPplthdt c00 gioi_thieumonhoc_v13.09a
Pplthdt c00 gioi_thieumonhoc_v13.09a
 
Jniについて
JniについてJniについて
Jniについて
 
Oop 2
Oop 2Oop 2
Oop 2
 
Phạm văn ất
Phạm văn ấtPhạm văn ất
Phạm văn ất
 
Oop 3
Oop 3Oop 3
Oop 3
 
De bai tap lap trinh lan 1
De bai tap lap trinh   lan 1De bai tap lap trinh   lan 1
De bai tap lap trinh lan 1
 
Pplthdt c02 lop_doi_tuong_v13.09a
Pplthdt c02 lop_doi_tuong_v13.09aPplthdt c02 lop_doi_tuong_v13.09a
Pplthdt c02 lop_doi_tuong_v13.09a
 
179887496 sdc1-bai tap-javacanban-5
179887496 sdc1-bai tap-javacanban-5179887496 sdc1-bai tap-javacanban-5
179887496 sdc1-bai tap-javacanban-5
 
Chuong6 (2)
Chuong6 (2)Chuong6 (2)
Chuong6 (2)
 
Bai06 mot sokythuattrongkethua
Bai06 mot sokythuattrongkethuaBai06 mot sokythuattrongkethua
Bai06 mot sokythuattrongkethua
 
Bai02 java introduction
Bai02 java introductionBai02 java introduction
Bai02 java introduction
 
C# coban
C# cobanC# coban
C# coban
 
Bai tap thuc hanh
Bai tap thuc hanhBai tap thuc hanh
Bai tap thuc hanh
 
Bai01 oop overview
Bai01 oop overviewBai01 oop overview
Bai01 oop overview
 
Oop unit 04 các kỹ thuật xây dựng lớp
Oop unit 04 các kỹ thuật xây dựng lớpOop unit 04 các kỹ thuật xây dựng lớp
Oop unit 04 các kỹ thuật xây dựng lớp
 
Lab lap trinhmang_v3
Lab lap trinhmang_v3Lab lap trinhmang_v3
Lab lap trinhmang_v3
 

Viewers also liked

Bài tập CTDL và GT 12
Bài tập CTDL và GT 12Bài tập CTDL và GT 12
Bài tập CTDL và GT 12Hồ Lợi
 
C5 classes and objects
C5 classes and objectsC5 classes and objects
C5 classes and objectsHồ Lợi
 
Bài tập CTDL và GT 2
Bài tập CTDL và GT 2Bài tập CTDL và GT 2
Bài tập CTDL và GT 2Hồ Lợi
 
Ctdl 2005 chuong 4
Ctdl 2005 chuong 4Ctdl 2005 chuong 4
Ctdl 2005 chuong 4Hồ Lợi
 
C4 data structures
C4 data structuresC4 data structures
C4 data structuresHồ Lợi
 
Ctdl 2005 chuong 2
Ctdl 2005 chuong 2Ctdl 2005 chuong 2
Ctdl 2005 chuong 2Hồ Lợi
 
Chương 3 - Hàng đợi
Chương 3 - Hàng đợi Chương 3 - Hàng đợi
Chương 3 - Hàng đợi Hồ Lợi
 
Phân tích một số thuật toán
Phân tích một số thuật toánPhân tích một số thuật toán
Phân tích một số thuật toánHồ Lợi
 
Bài tập CTDL và GT 7
Bài tập CTDL và GT 7Bài tập CTDL và GT 7
Bài tập CTDL và GT 7Hồ Lợi
 

Viewers also liked (20)

Chuong5 (2)
Chuong5 (2)Chuong5 (2)
Chuong5 (2)
 
Chuong4 (2)
Chuong4 (2)Chuong4 (2)
Chuong4 (2)
 
Chuong 1
Chuong 1Chuong 1
Chuong 1
 
Chuong2 c
Chuong2 c Chuong2 c
Chuong2 c
 
Bài tập CTDL và GT 12
Bài tập CTDL và GT 12Bài tập CTDL và GT 12
Bài tập CTDL và GT 12
 
C5 classes and objects
C5 classes and objectsC5 classes and objects
C5 classes and objects
 
Bài tập CTDL và GT 2
Bài tập CTDL và GT 2Bài tập CTDL và GT 2
Bài tập CTDL và GT 2
 
Ctdl 2005 chuong 4
Ctdl 2005 chuong 4Ctdl 2005 chuong 4
Ctdl 2005 chuong 4
 
Ctdl lab01
Ctdl lab01Ctdl lab01
Ctdl lab01
 
Gtrinh oop
Gtrinh oopGtrinh oop
Gtrinh oop
 
Cau 2
Cau 2Cau 2
Cau 2
 
Bai6 stacks
Bai6 stacksBai6 stacks
Bai6 stacks
 
C4 data structures
C4 data structuresC4 data structures
C4 data structures
 
Bai1 kdl
Bai1 kdlBai1 kdl
Bai1 kdl
 
C9 templates
C9 templatesC9 templates
C9 templates
 
Ctdl 2005 chuong 2
Ctdl 2005 chuong 2Ctdl 2005 chuong 2
Ctdl 2005 chuong 2
 
Chương 3 - Hàng đợi
Chương 3 - Hàng đợi Chương 3 - Hàng đợi
Chương 3 - Hàng đợi
 
Debug trong c
Debug trong cDebug trong c
Debug trong c
 
Phân tích một số thuật toán
Phân tích một số thuật toánPhân tích một số thuật toán
Phân tích một số thuật toán
 
Bài tập CTDL và GT 7
Bài tập CTDL và GT 7Bài tập CTDL và GT 7
Bài tập CTDL và GT 7
 

Similar to Chuong8 (2)

Ket tap, ke thua
Ket tap, ke thuaKet tap, ke thua
Ket tap, ke thuaTuan Do
 
Bài 2: Lập trình hướng đối tượng & Collection - Lập trình winform - Giáo trìn...
Bài 2: Lập trình hướng đối tượng & Collection - Lập trình winform - Giáo trìn...Bài 2: Lập trình hướng đối tượng & Collection - Lập trình winform - Giáo trìn...
Bài 2: Lập trình hướng đối tượng & Collection - Lập trình winform - Giáo trìn...MasterCode.vn
 
Lappj trình hướng đối tượng
Lappj trình hướng đối tượngLappj trình hướng đối tượng
Lappj trình hướng đối tượngHưởng Nguyễn
 
Oop unit 07 các kỹ thuật kế thừa
Oop unit 07 các kỹ thuật kế thừaOop unit 07 các kỹ thuật kế thừa
Oop unit 07 các kỹ thuật kế thừaTráng Hà Viết
 
10. C - Function And Operator Overload
10. C   - Function And Operator Overload10. C   - Function And Operator Overload
10. C - Function And Operator OverloadDarian Pruitt
 
Pdfc fast food-mastercode.vn
Pdfc fast food-mastercode.vnPdfc fast food-mastercode.vn
Pdfc fast food-mastercode.vnMasterCode.vn
 
Chuong9 lop vadoituong
Chuong9 lop vadoituongChuong9 lop vadoituong
Chuong9 lop vadoituongMinh Ngoc Tran
 
K33103350 tran doankimnhu_bai17_tin11
K33103350 tran doankimnhu_bai17_tin11K33103350 tran doankimnhu_bai17_tin11
K33103350 tran doankimnhu_bai17_tin11Tin5VungTau
 
Những điểm mới trong c# 3.0
Những điểm mới trong c# 3.0Những điểm mới trong c# 3.0
Những điểm mới trong c# 3.0Trần Thiên Đại
 
Thuc hanh ado.net_bai_03
Thuc hanh ado.net_bai_03Thuc hanh ado.net_bai_03
Thuc hanh ado.net_bai_03Thanh Điền
 

Similar to Chuong8 (2) (20)

Ket tap, ke thua
Ket tap, ke thuaKet tap, ke thua
Ket tap, ke thua
 
Bài 2: Lập trình hướng đối tượng & Collection - Lập trình winform - Giáo trìn...
Bài 2: Lập trình hướng đối tượng & Collection - Lập trình winform - Giáo trìn...Bài 2: Lập trình hướng đối tượng & Collection - Lập trình winform - Giáo trìn...
Bài 2: Lập trình hướng đối tượng & Collection - Lập trình winform - Giáo trìn...
 
Lappj trình hướng đối tượng
Lappj trình hướng đối tượngLappj trình hướng đối tượng
Lappj trình hướng đối tượng
 
Oop unit 07 các kỹ thuật kế thừa
Oop unit 07 các kỹ thuật kế thừaOop unit 07 các kỹ thuật kế thừa
Oop unit 07 các kỹ thuật kế thừa
 
Chuong 3
Chuong 3Chuong 3
Chuong 3
 
Chapter 3
Chapter 3Chapter 3
Chapter 3
 
10. C - Function And Operator Overload
10. C   - Function And Operator Overload10. C   - Function And Operator Overload
10. C - Function And Operator Overload
 
Lesson09
Lesson09Lesson09
Lesson09
 
Pdfc fast food-mastercode.vn
Pdfc fast food-mastercode.vnPdfc fast food-mastercode.vn
Pdfc fast food-mastercode.vn
 
Giáo trình c#
Giáo trình c#Giáo trình c#
Giáo trình c#
 
Chuong9 lop vadoituong
Chuong9 lop vadoituongChuong9 lop vadoituong
Chuong9 lop vadoituong
 
Oop 8
Oop 8Oop 8
Oop 8
 
Chapter 3 (cont)
Chapter 3 (cont)Chapter 3 (cont)
Chapter 3 (cont)
 
K33103350 tran doankimnhu_bai17_tin11
K33103350 tran doankimnhu_bai17_tin11K33103350 tran doankimnhu_bai17_tin11
K33103350 tran doankimnhu_bai17_tin11
 
Oop 5
Oop 5Oop 5
Oop 5
 
C9 templates
C9 templatesC9 templates
C9 templates
 
Những điểm mới trong c# 3.0
Những điểm mới trong c# 3.0Những điểm mới trong c# 3.0
Những điểm mới trong c# 3.0
 
Chuong 07 lop
Chuong 07 lopChuong 07 lop
Chuong 07 lop
 
Dotnet
DotnetDotnet
Dotnet
 
Thuc hanh ado.net_bai_03
Thuc hanh ado.net_bai_03Thuc hanh ado.net_bai_03
Thuc hanh ado.net_bai_03
 

More from Hồ Lợi

Tóm tắt các hàm chuẩn của c
Tóm tắt các hàm chuẩn của cTóm tắt các hàm chuẩn của c
Tóm tắt các hàm chuẩn của cHồ Lợi
 
Lect04 functions
Lect04 functionsLect04 functions
Lect04 functionsHồ Lợi
 
Ky thuatkhudequy
Ky thuatkhudequyKy thuatkhudequy
Ky thuatkhudequyHồ Lợi
 
Itt epc assignment
Itt epc assignmentItt epc assignment
Itt epc assignmentHồ Lợi
 
Huong danontapc
Huong danontapcHuong danontapc
Huong danontapcHồ Lợi
 
H hai epc_baitap
H hai epc_baitapH hai epc_baitap
H hai epc_baitapHồ Lợi
 
Giaotrinhbaitapkythuatlaptrinh
GiaotrinhbaitapkythuatlaptrinhGiaotrinhbaitapkythuatlaptrinh
GiaotrinhbaitapkythuatlaptrinhHồ Lợi
 
Giao trinh ky thuat lap trinh 2
Giao trinh ky thuat lap trinh 2Giao trinh ky thuat lap trinh 2
Giao trinh ky thuat lap trinh 2Hồ Lợi
 
Giao trinh c c++
Giao trinh c c++Giao trinh c c++
Giao trinh c c++Hồ Lợi
 
Epc assignment
Epc assignmentEpc assignment
Epc assignmentHồ Lợi
 
Epc test practical
Epc test practicalEpc test practical
Epc test practicalHồ Lợi
 
De thic++ --th
De thic++ --thDe thic++ --th
De thic++ --thHồ Lợi
 

More from Hồ Lợi (20)

Xu ly chuoi
Xu ly chuoiXu ly chuoi
Xu ly chuoi
 
Tóm tắt các hàm chuẩn của c
Tóm tắt các hàm chuẩn của cTóm tắt các hàm chuẩn của c
Tóm tắt các hàm chuẩn của c
 
T4
T4T4
T4
 
Nguyen lyoop
Nguyen lyoopNguyen lyoop
Nguyen lyoop
 
Lect04 functions
Lect04 functionsLect04 functions
Lect04 functions
 
Ky thuatkhudequy
Ky thuatkhudequyKy thuatkhudequy
Ky thuatkhudequy
 
Itt epc assignment
Itt epc assignmentItt epc assignment
Itt epc assignment
 
Huong danontapc
Huong danontapcHuong danontapc
Huong danontapc
 
H hai epc_baitap
H hai epc_baitapH hai epc_baitap
H hai epc_baitap
 
Giaotrinhbaitapkythuatlaptrinh
GiaotrinhbaitapkythuatlaptrinhGiaotrinhbaitapkythuatlaptrinh
Giaotrinhbaitapkythuatlaptrinh
 
Giao trinh ky thuat lap trinh 2
Giao trinh ky thuat lap trinh 2Giao trinh ky thuat lap trinh 2
Giao trinh ky thuat lap trinh 2
 
Giao trinh c c++
Giao trinh c c++Giao trinh c c++
Giao trinh c c++
 
File trong c_
File trong c_File trong c_
File trong c_
 
Epc assignment
Epc assignmentEpc assignment
Epc assignment
 
Epc test practical
Epc test practicalEpc test practical
Epc test practical
 
De thic++ --th
De thic++ --thDe thic++ --th
De thic++ --th
 
Dethi c++ -lt
Dethi c++ -ltDethi c++ -lt
Dethi c++ -lt
 
D05 stl
D05 stlD05 stl
D05 stl
 
Cpl test3
Cpl test3Cpl test3
Cpl test3
 
Cpl test2
Cpl test2Cpl test2
Cpl test2
 

Chuong8 (2)

  • 1. Lập trình hướng đối tượng C++ Giảng viên giảng dạy: Nguyễn Hữu Vân Long 1
  • 3. 3
  • 4. BM MTT&TT 4  Giới thiệu  Một số khái niệm  Thừa kế đơn  Hàm xây dựng  Hàm xây dựng sao chép  Hàm hủy  Tái định nghĩa...  Liên kết tĩnh và liên kết động  Đa thừa kế Nội dung bài giảng
  • 5. BM MTT&TT 5  Thừa kế  Là một trong những đặc tính mạnh nhất của OOP.  Là quá trình tạo ra các lớp mới từ những lớp đã có.  Về mặt ngữ nghĩa, lớp mới phải “là” lớp đã có với một vài đặc điểm hoặc tính năng mới.  Mục đích  Xây dựng lớp mới từ những lớp đã có.  Dùng lại mã (code reusability)  Sử dụng sự tương tự và sự khác nhau để mô hình hóa các lớp đối tượng có liên quan với nhau.  Là một cách để tổ chức thông tin. Giới thiệu
  • 6. BM MTT&TT 6 Xây dựng lớp mới từ lớp đã có void Thisinh2008::hienthi() { Thisinh::hienthi(); cout << "Noi thi: "; cout << noithi; } void Thisinh2008::nhap() { Thisinh::nhap(); cout << "Nhap noi thi: "; cin >> noithi; } Tận dụng lại các đoạn mã đã viết sẵn
  • 7. BM MTT&TT 7  Các loại hình dạng đều có một số thuộc tính, phương thức giống nhau. Các loài bò sát, động vật có vú, cá, … đều là động vật, đều cùng một loài. Sự tương tự và sự khác nhau
  • 8. BM MTT&TT 8  Lớp cha và lớp con  Lớp được thừa kế: Lớp cha (parent class), lớp cơ sở (base class).  Lớp thừa kế: Lớp con (child class), lớp dẫn xuất (derived class).  Các loại thừa kế  Thừa kế đơn: Lớp con thừa kế từ một lớp cha.  Đa thừa kế: Lớp con thừa kế từ nhiều lớp cha. Một số khái niệm
  • 9. BM MTT&TT 9  Một số đặc điểm  Quan hệ giữa lớp con và lớp cha là quan hệ “là”.  Lớp con, mặc nhiên sẽ có tất cả các thành phần của lớp cha. Tuy nhiên, nó chỉ truy xuất được các thành phần public hoặc protected.  Lớp con được tạo ra bằng cách  Thêm vào các thuộc tính mới.  Thêm vào các phương thức mới.  Thể hiện hóa một số thuộc tính của lớp cha.  Đổi kiểu dữ liệu của thuộc tính của lớp cha.  Tái định nghĩa, chồng các phương thức của lớp cha. Một số khái niệm
  • 10. BM MTT&TT 10  Lớp con chỉ thừa kế từ một lớp cha.  Cú pháp:     Dạng thừa kế: dùng để chỉ định các thành phần của lớp cha sẽ xuất hiện trong lớp con với thuộc tính truy xuất gì. Thừa kế đơn class <tên lớp con> : [dạng thừa kế] <tên lớp cha> { //các thành ph n (thu c tính/ph ng th c) c a l p conầ ộ ươ ứ ủ ớ ... }; Dạng t.kế Lớp cha public protected private (mặc nhiên) public public protected private protected protected protected private private private private private
  • 11. BM MTT&TT 11  Dạng thừa kế Thừa kế đơn class A { int x; void Fx (); public: int y; void Fy (); protected: int z; void Fz (); }; class B : A { // Thừa kế dạng private ……. }; class C : private A { // A là lớp cơ sở riêng của C ……… }; class D : public A { // A là lớp cơ sở chung của D ……… }; class E : protected A { // A: lớp cơ sở được bảo vệ ………. };
  • 12. BM MTT&TT 12  Chú ý: L p con th a k  (có) t t c  các thành ph n c a l p cha nh ng ch  ớ ừ ế ấ ả ầ ủ ớ ư ỉ đ c truy xu t các thành ph n ượ ấ ầ public ho c ặ protected class Diem { int x, y; public: void ganDiem(int h, int t) { x = h; y = t; } void hienthi() { cout << "(" << x << ", "<< y << ")"; } void doiDiem(int dx, int dy) { x += dx; y += dy; } ... }; class Diemmau : public Diem { int mau; //b sung thêm thu c tínhổ ộ “màu” public: void ganDM(int h, int t, int m) { ganDiem(h, t); mau = m; } void hienthiDM() { hienthi(); cout << ", mau: " << mau; } }; void main() { Diemmau a; a.ganDM(0, 0, 7); a.hienthiDM(); cout << endl; a.doiDiem(2, 1); a.hienthiDM(); } a x, y, mau ganDiem() hienthi() doiDiem() ganDM() hienthiDM() Thừa kế đơn
  • 13.  Thứ tự khởi tạo: Thành phần lớp cha => Thành phần lớp con => Hàm xây dựng của lớp cha sẽ được gọi trước, sau đó là hàm xây dựng của lớp con.  Khi gọi hàm xây dựng: phải gọi hàm xây dựng của lớp cha trước khi khởi tạo các dữ liệu của lớp con.  Nếu hàm XD của lớp con không gọi hàm XD lớp cha một cách tường minh thì hàm xây dựng không đối số sẽ được gọi. Thừa kế đơn - Hàm xây dựng
  • 14.  Ví dụ Thừa kế đơn - Hàm xây dựng int main() { B objB; return 0; } class A { public: A() { cout << "A's constructorn"; } }; class B : public A { public: B() { cout << "B's constructorn"; } };
  • 15.  Cú pháp gọi hàm xây dựng của lớp cha: Thừa kế đơn - Hàm xây dựng <phần khai báo hàm XD lớp con> : <tên lớp cha>([DS đối số]) { //thân hàm XD c a l p conủ ớ } Tùy vào danh sách đối số mà hàm xây dựng tương ứng của lớp cha sẽ được gọi class X { int a; public: //X’s constructors X() { a = 0; } X(int aa) { a = aa; } //. . . }; class Y : public X { int b; public: //Y’s constructors Y() : X() { b = 0; } Y(int aa, int bb) : X(aa) { b = bb; } //. . . }; Gọi hàm XD của lớp cha
  • 16. Thừa kế đơn - Hàm xây dựng mau: void main() { Diemmau a; Diemmau b(1, 1, 3); } x: y: 0 0 0 a //th a k t l p Diemừ ế ừ ớ Diem() mau = 0; mau: x: y: 1 1 3 b //th a k t l p Diemừ ế ừ ớ Diem(1, 1) mau = 3; class Diem { int x, y; public: Diem() { x = y = 0; } Diem(int h, int t) { x = h; y = t; } }; class Diemmau : public Diem { int mau; public: Diemmau() : Diem() { mau = 0; } Diemmau(int h, int t, int m) :Diem(h, t) { mau = m; } }; Gọi hàm XD của lớp cha
  • 17.  Hàm xây dựng sao chép  Bên trong mỗi đối tượng của lớp con, luôn có các thành phần dữ liệu của lớp cha trong hàm XDSC của lớp con phải gọi hàm XDSC của lớp cha để đảm bảo các dữ liệu này cũng được sao chép.  Cú pháp gọi hàm XDSC của lớp cha Thừa kế đơn - Hàm XD sao chép <tên lớp con>(const <tên lớp con>& obj) : <tên lớp cha>(obj) { //thân hàm XDSC c a l p conủ ớ } Prototype hàm XDSC lớp con Gọi hàm XDSC lớp cha Các thành phần dữ liệu của lớp cha bên trong ĐT obj sẽ được sử dụng để sao chép cho các t.phần dữ liệu của lớp cha của ĐT mới.
  • 18. 18 //constructors Emp::Emp () : Person() { dept = new char[30]; strcpy(dept, ""); salary = 0.0; } Emp::Emp (char* n, char* d, float s) : Person(n) { dept = strdup(d); salary = s; } //copy constructor Emp::Emp(const Emp& e) :Person(e) { dept = strdup(e.dept); salary = e.salary; } //Constructors Person::Person() { name = new char[50]; strcpy(name, ""); } Person::Person(char* n) { name = strdup(name); } //copy constructor Person::Person(const Person& p) { name = strdup(p.name); } Gọi hàm XDSC cho lớp cha Thừa kế đơn - Hàm XD sao chép
  • 19.  Thuộc tính của lớp con trùng tên thuộc tính của lớp cha.  Trong lớp con, nếu ta truy xuất đến dữ liệu trùng tên đó thì sẽ truy xuất đến dữ liệu của lớp con.  Truy xuất dữ liệu lớp cha : <Tên lớp cha>::<dữ liệu> Thừa kế đơn - Tái ĐN dữ liệu TV class LopCha { public: int a; LopCha() { a= 0; } }; class LopCon : public LopCha { public: int a; LopCon(); void Hien(); }; LopCon::LopCon() : LopCha() { a = 1; } void LopCon::Hien() { cout << a << LopCha::a; } void main() { LopCon x; x.Hien(); cout << x.a << x.LopCha::a; }
  • 20.  Hàm thành viên của lớp con trùng tên với hàm thành viên của lớp cha.  Gọi hàm trùng tên => gọi hàm của lớp con.  Gọi hàm của lớp cha : <Tên lớp cha>::<tên hàm>(…) Thừa kế đơn - Tái ĐN dữ liệu TV class Diem { int x, y; public: ... void Hien() { cout<<“(”<<x<<“,”<<y<<“)”;} }; class DiemMau : public Diem { int mau; public: void Hien(); ... }; void DiemMau :: Hien() { Diem::Hien(); cout<<“ mau ”<<mau; } void main() { DiemMau a(2,5,4); a.Hien(); a.DiemMau::Hien(); DiemMau b=a; b.Diem::Hien(); }
  • 21.  Cũng tương tự như hàm XDSC, hàm tái định nghĩa toán tử gán ‘=’ của lớp con cũng phải gọi đến hàm tái định nghĩa tác tử ở lớp cha để thực hiện sự sao chép cho các thành phần của lớp cha. Thừa kế đơn - Tái ĐN phép gán //assignment operator overloading Person& Person::operator= (const Person& p) { delete[] name; name = strdup(p.name); return *this; } Emp& Emp::operator= (const Emp& e) { Person::operator=(e); delete[] dept; dept = strdup(e.dept); salary = e.salary; } Gọi hàm tái ĐN phép gán cho lớp cha
  • 22.  Hủy đối tượng, hàm hủy:  Khi một đối tượng thuộc lớp con bị hủy, hàm hủy của lớp cha sẽ tự động được gọi (nếu có), ngay cả trong trường hợp lớp con không có hàm hủy.  Hàm hủy của lớp con (nếu có) không cần gọi đến hàm hủy của lớp cha.  Thứ tự: hàm hủy lớp con => hàm hủy lớp cha. Thừa kế đơn - Hàm hủy class Person { char* name; public: //. . . ~Person() {delete[] name; } //. . . }; class Emp { char* dept; float salary; public: //. . . ~Emp() {delete[] dept; } //. . . };
  • 23. Thừa kế đơn - Hàm hủy class X { int* x_data; int x_size; public: //...constructors + member functions //destructor ~X() { cout << "X's destructorn"; delete[] x_data; } }; class X : public Y { int* x_data; int x_size; public: //...constructors + member functions //destructor ~Y() { cout << “Y's destructorn"; delete[] y_data; } }; int main() { Y yObj; return 0; } Trường hợp Y không có hàm hủy
  • 24.  Sự tương thích giữa đối tượng của lớp con và đối tượng của lớp cha Liên kết tĩnh và liên kết động • Một đối tượng thuộc lớp con có thể được gán cho một đối tượng thuộc lớp cha. • Một con trỏ thuộc lớp cha có thể trỏ đến một đối tượng thuộc lớp con. • Không có chiều ngược lại. 24 void main() { LopCha a; LopCon b; a = b; b = a; // Sai LopCha *pa; pa = &a; LopCon *pb; pb = &b; pa = &b; pb = &a; // Sai } Con trỏ của lớp cha có thể trỏ đến đối tượng của lớp con Có thể gán Cha = Con Hổn
  • 25.  Liên kết tĩnh  Sự liên kết giữa con trỏ đối tượng và hàm thành viên được thực hiện lúc biên dịch => Con trỏ thuộc lớp nào sẽ gọi hàm thành viên của lớp đó. Liên kết tĩnh và liên kết động class LopCha { ... public: … void HamThanhVien() { cout<<“Ham cua Lop Cha”; } }; class LopCon : public LopCha { ... public: … void HamThanhVien() { cout<<“Ham cua Lop Con”; } }; void main() { LopCha a; LopCha *pa=&a; pa->HamThanhVien(); //Lớp cha LopCon b; LopCon *pb=&b; pb->HamThanhVien(); //Lớp con pa= &b; pa->HamThanhVien(); //Lớp cha pb= &a; //Báo lỗi }
  • 26. 26 bObj draw() dObj draw() Base draw() Base* bp Base bObj, *bp; Derived dObj; bp = &bObj; bp->draw(); //G i hàm draw() c a l p Baseọ ủ ớ bp = &dObj; bp->draw(); //G i hàm draw() c a l p Baseọ ủ ớ Liên kết tĩnh và liên kết động
  • 27.  Liên kết động  Sự liên kết giữa con trỏ đối tượng và hàm thành viên được thực hiện lúc thực thi chương trình, con trỏ đang trỏ tới đối tượng thuộc lớp nào thì hàm thành viên của lớp đó được gọi.  Chỉ thực hiện được khi hàm thành viên được khai báo là hàm ảo (virtual function) trong lớp cha.  Thể hiện cho tính đa hình của lập trình Hướng đối tượng: cùng một thông điệp nhưng có thể được ứng xử khác nhau tùy vào từng “hoàn cảnh” cụ thể. Liên kết tĩnh và liên kết động class LopCha { ... public: … virtual void HamAo() { cout<<“Ham cua Lop Cha”; } }; class LopCon : public LopCha { ... public: … void HamAo() { cout<<“Ham cua Lop Con”; } }; void main() { LopCha a; LopCha *pa=&a; pa->HamAo(); //Lớp cha LopCon b; LopCon *pb=&b; pb->HamAo(); //Lớp con pa= &b; pa->HamAo(); //Hàm lớp con pb= &a; //Báo lỗi }
  • 28.  Hàm ảo  Cú pháp: khai báo thêm từ khóa virtual trước hàm.  Dùng chung với tính liên kết động => tính đa hình  Hàm hoàn toàn ảo  Là hàm ảo chỉ có khai báo, không có định nghĩa  Cú pháp: chỉ khai báo tên trong lớp cha và gán=0.  Hàm hoàn toàn ảo phải định nghĩa lại trong lớp con. Liên kết tĩnh và liên kết động class Base { public: virtual void draw() { ... } }; class Base { public: virtual void draw() = 0; }; class Base { public: virtual void draw() = 0; };
  • 29. Liên kết tĩnh và liên kết động class Base { public: void virtual draw() { ... } }; class Derived : public Base { public: void draw() { . . .} }; Base bObj, *bp; Derived dObj; bp = &bObj; bp->draw(); //Goi ham draw() cua lop Base bp = &dObj; bp->draw(); //Goi ham draw() cua lop Derived bObj draw() dObj draw() Base draw() Base* bp
  • 30. Liên kết tĩnh và liên kết động class Shape { //. . . public: virtual void draw() = 0; }; class Circle : public Shape { //. . . public: void draw() { cout << "Circle's draw()n"; } }; class Triangle : public Shape { //. . . public: void draw() { cout << "Triangle's draw(n)"; } }; class Rectangle : public Shape { //. . . public: void draw() { cout << "Rectangle's draw()n"; } }; void main() { Shape* shapeArr[4]; shapeArr[0] = new Circle(); shapeArr[1] = new Triangle(); shapeArr[2] = new Circle(); shapeArr[3] = new Rectangle(); for (int i=0; i<4; i++) shapeArr[i]->draw(); }
  • 31.  Hàm hủy  Hàm hủy của lớp cơ sở nên được khai báo là hàm ảo.  Lý do: Sử dụng tính liên kết động để hủy đối tượng.  Lớp ảo  Là lớp có chứa ít nhất một hàm ảo.  Không thể tạo đối tượng thuộc lớp ảo.  Tuy nhiên, có thể tạo con trỏ thuộc lớp ảo.  Ví dụ: Lớp Shape trong VD trước là lớp ảo. Liên kết tĩnh và liên kết động
  • 32.  Lớp con thừa kế từ nhiều hơn một lớp cha.  Cú pháp: Đa thừa kế class <tên lớp con> : {[dạng thừa kế] <tên lớp cha>} {,… n} { //các thành ph n (thu c tính/ph ng th c) c a l p conầ ộ ươ ứ ủ ớ ... }; class Z : public X, public Y { //... }; class X { //... }; class Y { //... };
  • 33.  Ưu điểm  Tận dụng được những thành phần đã có sẵn của lớp cha:  Dữ liệu thành viên  Hàm thành viên  Thuận lợi khi sử dụng kết hợp với hàm ảo.  Vấn đề cần lưu ý khi sử dụng thừa kế bội  Cạnh tranh trong thừa kế bội.  Thiết kế sơ đồ thừa kế phải đúng ý nghĩa.  Nên hạn chế và cẩn thận khi sử dụng thừa kế bội. Đa thừa kế SinhViên SinhViênTạiChức – mã số NhânViên – mã số Dữ liệu của SinhViên Dữ liệu của NhânViên Dữ liệu của SinhViênTạiChức Tạo ra đối tượng
  • 34. class XeDien { int loaibinhdien; int thoigian; float tocdo; public: XeDien() { … } XeDien(int b, int tg, float td) { … } … }; class XeDapDien : public XeDap, public XeDien { … public: XeDapDien(); XeDapDien( char*, char*, int , int , int , float ); … }; XeDapDien::XeDapDien () : XeDap(), XeDien() { … } XeDapDien::XeDapDien ( char* a, char* b, int c, int d, int e, float f ) : XeDap(a, b, c), XeDien(d,e,f) { … } … class XeDap { char loai[10]; char* mau; int chieucao; public: XeDap() { … } XeDap(char* l, char* m, int c) { … } … }; Khai báo lớp trong thừa kế bội Gọi hàm xây dựng của các lớp cha Đa thừa kế
  • 35. 35 class Student { //educational background char school[30]; //name of school char degree[20]; //highest degree public: void getedu() { cout << "School: "; cin >> school; cout << "Highest degree: "; cin >> degree; } void putedu() { cout << "School: " << school; cout << “Degree: " << degree; } }; class employee { char name[40]; //employee name unsigned long ID; //employee ID public: void getdata() { cout << "Name: "; cin >> name; cout << "ID: "; cin >> number; } void putdata() { cout << "Name: " << name; cout << "ID: " << number; } }; class manager : employee, student { char title[20]; //”vice-president” etc. double dues; //golf club dues public: void getdata() { employee::getdata(); cout << "Title: "; cin >> title; cout << "Club dues: "; cin >> dues; student::getedu(); } void putdata() { employee::putdata(); cout << "nTitle: " << title; cout << "nClub dues: " << dues; student::putedu(); } }; Đa thừa kế
  • 36.  Thứ tự khởi tạo: giống như trong Thừa kế đơn, các thành phần dữ liệu của lớp cha sẽ được khởi tạo trước, sau đó tới lớp con.  Hàm XD/XDSC của lớp con cần gọi đến hàm XD/XDSC thích hợp ở lớp cha.  Cú pháp: tương tự trong Thừa kế đơn. Đa thừa kế - Khởi tạo class X { // data public: //methods }; class Y { // data public: //methods }; class Z : public X, private Y { //data public: //constructor Z(...) : X(...), Y(...) { //... } //copy constructor Z(const Z& obj) : X(obj), Y(obj) { //... } };
  • 37.  Trong Đa thừa kế, ta thường gặp phải một số vấn đề  Sự trùng lặp dữ liệu của lớp cơ sở chung trong lớp kế thừa.  Xung đột tên của các hàm thành viên hoặc dữ liệu thành viên giữa các lớp cơ sở. Đa thừa kế - Một số vấn đề SaleManger SalePerson Manager EmployeeEmployee
  • 38.  Cách giải quyết các vấn đề trên  Sự trùng lặp dữ liệu của lớp cơ sở chung: Dùng lớp cơ sở ảo. Đa thừa kế - Một số vấn đề class A { // . . . }; class X : public A { // . . . }; class Y : public A { // . . . }; class X : virtual public A { // . . . }; class Y : virtual public A { // . . . }; class Z : public X, public Y { //. . . }; Z X Y AA Z X Y A (Dùng chung bởi X và Y)
  • 39.  Cách giải quyết các vấn đề trên  Dùng tên lớp cơ sở một cách tường minh trong truy xuất các thành phần trùng tên trong lớp cơ sở. Đa thừa kế - Một số vấn đề class X { public: void print() { cout << "X's print()"; } }; class Y : virtual public X { public: void print() { cout << "Y's print"; } }; class T : virtual public X { public: void print() { cout << "T's print"; } }; class U : public Y, public T { public: void print() { cout << "U's print"; } }; int main() { U u; u.print(); // U's print invoked u.X::print(); // X's print invoked u.Y::print(); // Y's print invoked u.T::print(); // T's print invoked return 0; }