Professional Documents
Culture Documents
Trang 1
Lập trình hướng đối tượng với C++
+ Phần này sẽ giúp các bạn hiểu được cách định nghĩa một lớp và khai báo một đối tượng của
lớp đó.
+ Thực hiện các bước sau:
+ Tạo một file mới.
+ Trong cửa sổ soạn thảo Gõ vào đoạn chương trình sau:
#include <iostream.h>
#include <conio.h>
void main()
{
MyFirstClass aObject; // Khai bao mot doi tuong
aObject.dataMember = 50;
cout << "Du lieu cua doi tuong la: " << aObject.dataMember;
getch();
}
+ Lưu thành file FirstClass.CPP
+ Biên dịch và chạy chương trình, kết quả như sau:
void main()
{
clrscr();
CPoint p1; // Khai bao 1 doi tuong cua lop CPoint
CPoint *p; // Khai bao mot con tro doi tuong CPoint
Trang 3
Lập trình hướng đối tượng với C++
cout << "\nToa do cua con tro p sau khi goi p->Init(100,100) :";
p->Display(); // hay nho, voi con tro phai la ->, khong phai "."
cout << "\nVa sau khi goi p->Move(10,10) ";
p->Move(10,10); // Chay mot doan nua roi hien thi
p->Display(); // Hien thi
cout << endl << endl << "An phim bat ky..." ;
getch();
}
+ Lưu file vào đĩa.
+ Kết quả khi chạy chương trình.
+ Ghi chú : Từ khoá public cho ta biết tầm vực của hàm hay biến được khai báo theo sau nó,ý
nghĩa của từ khoá này sẽ được làm rõ trong bài thực hành sau.
Bài tập làm thêm
Bài 1: Viết chương trình tính diện tích của hình chữ nhật và kiểm tra xem hình chữ nhật đó có
phải là hình vuụng hay không
Hướng dẫn: Định nghĩa một lớp hinh chữ nhật Rect như sau;
Class CRect // Lop hinh chu nhat
{
private :
int nWidth; // Chieu rong
int nHeight; // Chieu dai
public :
void Input(); // Nhap kich thuoc tu ban phim
void Init(int w, int h); // Khoi tao kich thuoc
long Area(); // Tra ve dien tich
int IsSquare(); // Co la hinh vuong khong.
] ; // Ket thuc phan dinh nghia (Khai bao) lop
+ Hàm Input cho phép người dùng nhập các chiều của hình chữ nhật từ bàn phím.
+ Hàm Init khởi tạo các chiều của hình chữ nhật với các giá tri w và h.
+ Hàm Area trả về diện tớch của hình vuụng.
+ Hàm IsSquare sẽ trả về 1 nếu hình chữ nhật là hình vuụng, nếu không thì trả về 0.
Bài 2: Viết chương trình tạo ra lớp phõn số, trong đó có các hàm thành viên cho phép nhập vào
phân số, khởi tạo phân số, kiểm tra tính hợp lệ của phân số, rút gọn phân số và in phân số ra màn
hình.
Bài 3: Xây dựng lớp "ngày" cho phép nhập vào một ngày, khởi tạo một ngày, kiểm tra ngày hợp
lệ, tớnh ngày tiếp theo, và in ngày ra màn hình.
Hướng dẫn: Định nghĩa lớp ngày như sau
Class CDate // Lop ngay
{
private :
Trang 4
Lập trình hướng đối tượng với C++
public :
void Input(); // Nhap ngay thang tu ban phim
void Init(int d, int m, int y);// Khoi tao gia tri
int IsValid(); // Kiem tra ngay xem co hop le ?
void NextDay(CDate &objNext); // Tinh ngay tiep theo
void Display();
Ư ; // Ket thuc phan dinh nghia (Khai bao) lop
Trang 5
Lập trình hướng đối tượng với C++
#include <iostream.h>
class date
{
public:
int day;
int month;
int year;
};
void main()
{
date today;
today.day = 25;
today.month = 12;
today.year = 2001;
cout << “\n Ngay la “<< today.day<< “/” ;
cout << today.month << “/” << today.year << endl;
}
Kết quả trên màn hình là (nhấn tổ hợp phím Alt F5 để xem) :
Ngay la 25/12/2001
Trong chương trình trên, lớp date được cài đặt có ba thuộc tính được khai báo là public và
các thuộc tính này có thể được truy xuất từ bên ngoài lớp. Ở đây chúng được truy cập từ hàm
main(). Để truy xuất các thành phần của lớp, trong C++ sử dụng toán tử dấu chấm “.”;
Từ khoá endl dựng là ký tự xuống dòng hoặc làm cho đầy dòng, nó tương tự như ‘\n’.
5. Đóng file “date211.cpp”
2.1.2 Thành phần dữ liệu “private” trong lớp
Trang 6
Lập trình hướng đối tượng với C++
Khi không dựng từ khoá public thì trình biờn dịch C++ sẽ xem các thành phần của lớp được khai
báo là private. Các thành phần được khai báo là private sẽ không truy cập trực tiếp được từ bên
ngoài lớp.
#include <iostream.h>
class date
{ //mac đinh cac thanh phan se đuoc xem la private
int day;
int month;
int year;
};
void main()
{
date today;
today.day = 25;
today.month = 12;
today.year = 2001;
cout << “\n Ngay la “<< today.day<< “/” ;
cout << today.month << “/” << today.year << endl;
}
2.1.3 Sử dụng các hàm thành viên truy cập các thuộc tớnh dữ liệu “private”
Chương trình dưới đây minh hoạ việc sử dụng các hàm thành viên để truy cập các thuộc tính của
lớp.
Trang 7
Lập trình hướng đối tượng với C++
#include <iostream.h>
class date
{
private:
int day;
int month;
int year;
public:
void getdate (void)
{
cout << “\n Nhap vao ngay (dd): “;
cin >> day;
cout << “\n Nhap vao thang (mm): “ ;
cin >> month;
cout << “\n Nhap vao nam (yy): “ ;
cin >> year;
Trang 8
Lập trình hướng đối tượng với C++
Chương trình trên cài đặt lớp “date”có ba thuộc tính day, month, year kiểu số nguyên và
được khai báo là private, hai hàm getdate(), display() được định nghĩa ở trong lớp và được khai
báo là public, hai hàm này có thể được truy suất từ bên ngoài lớp.
Trong hàm main() có khai báo đối tượng (object) today có kiểu là date. Dùng toán tử dấu chấm
“.” để truy xuất các hàm, gọi today.getdate() để nhập dữ liệu cho đối tượng today, today.display()
để thể hiện trên màn hình. Như vậy, để truy xuất các thuộc tính có khai báo là private bạn phải
thông qua các hàm thành viên.
2.1.4 Truyền tham số đối tượng cho các hàm thành viên
1. Tạo file mới
2. Gõ đoạn chương trình sau
#include <iostream.h>
class Time
{
private:
int hours, minutes, seconds;
public:
void getinfo (void)
{
cin >> hours >> minutes >> seconds;
} //ket thuc ham getinfo
void display (void)
{
cout<<hours<<‘:’<<minutes<<‘:’<<seconds<< endl;
} // ket thuc ham display
Trang 9
Lập trình hướng đối tượng với C++
};
void main()
{
Time one, two, three;
cout << “\n Nhap vao thoi gian mot (gio phut giay): ”;
one.getinfo();
cout << “\n Nhap vao thoi gian hai (gio phut giay): ”;
two.getinfo();
three.addit(one, two);
cout << “Ket qua la “;
three.display();
}
Trong hàm main() ở chương trình trên có khai báo ba đối tượng của lớp Time là one, two,
three. Thông tin của đối tượng one, two được cung cấp thông qua gọi hàm getinfo của từng đối
tượng. Đối tượng three có được thông tin thông qua gọi hàm addit của nó, three.addit(one, two);
ở lời gọi hàm này, ta đó truyền hai đối tượng one và two vào cho hàm addit, trong hàm addit aa,
bb sẽ là các đối tượng đại diện cho one, two và các biến hours, minutes, seconds là các thuộc tính
của đối tượng three.
Trang 10
Lập trình hướng đối tượng với C++
#include <iostream.h>
class Student
{
private:
int rollno;
int marks;
public:
void getinfo ()
{
cout << “Nhap vao ma so sinh vien: “;
cin >> rollno ;
cout << “Nhap vao diem: “;
cin >> marks ;
} //ket thuc ham getinfo
void display ()
{
cout<<rollno<<‘\t’<<marks<< endl;
} // ket thuc ham display
int getmarks()
{
return marks;
} // ket thuc ham getmarks
void main()
{
Student stulist[100];
float total, average;
int no, i;
total = 0.0;
cout << “\n Nhap vao so luong sinh vien: ”;
cin >> no ;
Trang 11
Lập trình hướng đối tượng với C++
Trang 12
Lập trình hướng đối tượng với C++
#include <iostream.h>
#include <conio.h>
class CRectangle
{
private:
int nHeight; //chieu dai hinh chu nhat
int nWidth; //chieu rong hinh chu nhat
public:
CRectangle(); //ham constructor
int Area(); //ham tinh dien tich hinh chu nhat
void Initialize(int,int);
~CRectangle(); //ham destructor
};
CRectangle::CRectangle()
{
cout << "Khoi tao cac thuoc tinh bang ham constructor\n";
nHeight = 6;
nWidth = 8;
}
int CRectangle::Area()
{
return nHeight*nWidth;
}
Trang 13
Lập trình hướng đối tượng với C++
CRectangle::~CRectangle()
{
cout << "destructor dang duoc goi\n";
}
void main()
{
clrscr();
CRectangle Box,Square;
cout << "Dien tich cua Box la: "<< Box.Area() << "\n";
cout << "Dien tich cua Square la: "<< Square.Area() << "\n";
Box.Initialize(12,8);
Square.Initialize(8,8);
cout << "Dien tich cua Box la: "<< Box.Area() << "\n";
cout << "Dien tich cua Square la: "<< Square.Area() << "\n";
}
Khi chạy chương trình trên chúng ta sẽ thu được kết quả như sau:
Khoi tao cac thuoc tinh bang ham constructor
Khoi tao cac thuoc tinh bang ham constructor
Dien tich cua Box la: 48
Dien tich cua Square la: 48
khoi tao lai hinh chu nhat voi cac bien duoc dua vao
khoi tao lai hinh chu nhat voi cac bien duoc dua vao
Dien tich cua Box la: 96
Dien tich cua Square la: 64
destructor dang duoc goi
destructor dang duoc goi
Chương trình trên khai báo một lớp tên là CRectangle. Trong lớp có 2 biến private kiểu integer.
Trong các hàm public có một hàm constructor và một hàm destructor. Hàm constructor thì có cùng
tên với tên lớp của nó. Hàm destructor được đặt tên cũng theo một cách như vậy nhưng có thêm
dấu ~ ở phía trước tên hàm đó.
Mỗi lần một đối tượng được tạo ra trong hàm main() thì hàm constructor của nó sẽ được thực hiện.
Trong hàm main() có khai báo hai đối tượng thuộc lớp CRectangle. Trong hàm constructor có đưa
vào lệnh để hiển thị dòng "Khoi tao cac thuoc tinh bang ham constructor" trên màn hình. Trong
hàm main khi ta vừa khai báo 2 đối tượng Box và Square thì các constructors của nó được gọi nên
ở màn hình output sẽ có hai dòng:
Khoi tao cac thuoc tinh bang ham constructor
Và diện tích của 2 hình chữ nhật này sẽ được tính dựa trên các giá trị đã được khởi tạo trong hàm
constructor (nWidth = 8,nHeight = 6). Khi đó diện tích của hai hình chữ nhật này là 48.
Sau đó chương trình sẽ gọi hàm Initialize() của Box và Square để gán lại giá trị mới cho các thuộc
tính nWidth, nHeight của từng đối tượng.
Trang 14
Lập trình hướng đối tượng với C++
Box.Initialize(12,8);
Square.Initialize(8,8);
Khi đó diện tích của Box và Square lần lượt là 96, 64. Vì các giá trị thuộc tính của 2 hình chữ
nhật này đã được gán lại với các giá trị khác nhau. Khi hàm Initialize() của Box và Square được
gọi thì màn hình output sẽ in ra màn hình 2 dòng:
khoi tao lai hinh chu nhat voi cac bien duoc dua vao
khoi tao lai hinh chu nhat voi cac bien duoc dua vao
Khi 2 đối tượng Box và Square bị hủy vào cuối hàm main, hàm destructor của các đối tượng
này sẽ được tự động thực thi. ở trong màn hình output chúng ta sẽ thấy 2 dòng sau, do 2 hàm
destructor được thực hiện:
destructor dang duoc goi
destructor dang duoc goi
Trong chương trình dưới đây, chúng ta sẽ viết một lớp với tên là CTime. Không giống như lớp
CRectangle ở trên trong lớp CTime còn có thêm một constructor khởi tạo các giá trị hours, minutes,
seconds của lớp CTime. Và qua đó các bạn sẽ thấy rõ hơn các hàm constructor được gọi khi với
tham số hoặc không có tham số. Và lớp này có một hàm destructor để gọi khi lớp bị hủy.
Các bạn tạo file và đánh vào chương trình sau:
#include <iostream.h>
#include <conio.h>
class CTime
{
private:
int nHours,nMinutes,nSeconds;
//bien luu gio, phut, giay cua lop CTime
public:
CTime(); //ham constructor khong doi so
CTime(int h,int m,int s);//ham constructor 3 doi so
void Display();
void AddIt(CTime Time1,CTime Time2);
~CTime(); //ham destructor
};
CTime::CTime()
{
cout << "ham constructor mac dinh\n";
nHours = nMinutes = nSeconds = 0;
}
void CTime::Display()
{
cout << nHours << ':' << nMinutes << ':' << nSeconds << endl;
Trang 15
Lập trình hướng đối tượng với C++
CTime::~CTime()
{
cout << "Ham destructor\n";
}
void main()
{
clrscr();
CTime Result;
CTime T1(1,49,50);
CTime T2(3,40,30);
Result.AddIt(T1,T2);
cout << "Ket qua la: ";
Result.Display();
}
Kết quả sau khi thực hiện chương trình trên là:
ham constructor mac dinh
ham constructor voi 3 doi so
ham constructor voi 3 doi so
Ham destructor
Ham destructor
Ket qua la: 5:30:20
Ham destructor
Ham destructor
Ham destructor
Trong chương trình trên, lớp CTime có đến 2 constructors để khởi tạo nó. Một constructor
thì không có đối số và một còn lại thì có 3 đối số.. Hàm constructor không có đối số là hàm
constructor mặc định sẽ được gọi. Trong hàm main(), biến Result, khi khai báo:
Trang 16
Lập trình hướng đối tượng với C++
CTime Result;
Thì hàm constructor sẽ được gọi cho đối tượng Result là constructor mặc định không có đối số. Vì
thế trong màn hình output chúng ta sẽ thấy xuất hiện dòng sau:
ham constructor mac dinh
Với hàm constructor mặc định này thì cả ba thuộc tính của lớp CTime là nHours, nMinutes,
nSeconds đều gán giá trị là 0. Khi đối tượng được khai báo như sau thì constructor còn lại sẽ được
gọi:
CTime T1(1,49,50);
CTime T2(3,40,30);
Khi khai báo hai đối tượng T1 và T2 chúng ta đưa vào cho Time1, Time2 ba đối số, khi đó hàm
constructor CTime(int,int,int) sẽ được gọi với 3 đối số là 3 giá trị chúng ta đưa vào. Vì hai đối
tượng được khai báo nên constructor sẽ được gọi lần lượt cho T1 và T2 nên chúng ta sẽ nhận được
tiếp theo 2 dòng sau trong màn hình output:
ham constructor voi 3 doi so
ham constructor voi 3 doi so
Hai dòng tiếp theo trong màn hình output chúng ta sẽ thấy hai dòng giống nhau là:
Ham destructor
Nếu như chỉ hiểu theo nghĩa là hàm destructor chỉ được gọi khi một đối tượng bị hủy thì chúng ta
thấy trong chương trình 3 đối tượng khai báo của chúng ta vẫn chưa bị hủy cho tới dòng lệnh tiếp
theo sau nó. Thật ra, trong chương trình của chúng ta có gọi hàm AddIt của đối tượng Result, với
2 đối số của nó là T1 và T2. Mà hàm destructor cũng sẽ được thực hiện tại cuối bất kỳ hàm nào
mà đối số của nó là một lớp hay một đối tượng nào đó được khai báo trong hàm. Đây chính là lý
do mà hai dòng hiển thị của hàm destructor hiện ra màn hình output. Và hàm destructor của lớp
CTime cũng sẽ được gọi 3 lần vào cuối hàm main(), vì khi đó 3 đối tượng Result, T1, T2 bị hủy.
Trong lớp CTime xuất hiện cùng một lúc hai hàm constructor với hai tham số khác nhau ta gọi đó
là đa năng hóa hàm constructor mà ta sẽ xét ở phần sau.
Trong C++ toán tử new thường xuất hiện trong hàm constructors khi khởi tạo đối tượng.
Và vùng nhớ cấp phát này phải được xóa khi đốí tượng bị hủy, nên toán tử delete dùng để xóa
vùng nhớ được cấp phát bằng toán tử new thường được để trong hàm destructors.
Trong chương trình dưới đây chúng ta sẽ xây dựng một lớp mà thuộc tính của nó là một chuỗi.
Trong hàm constructor của lớp này chúng ta sẽ sử dụng toán tử new để cấp phát vùng nhớ cho
chuỗi này. Trong hàm destructor của lớp chúng ta sẽ dùng toán tử delete để xóa vùng nhớ này đi.
Các bạn hãy mở một file mới và đánh vào đó chương trình sau:
#include <iostream.h>
#include <conio.h>
#include <string.h>
class CString
{
private:
char* strName;
public:
CString(char* str)
{
int size = strlen(str);
strName = new char[size + 1];
strcpy(strName,str);
}
Trang 17
Lập trình hướng đối tượng với C++
void Display()
{
cout << strName << endl;
cout<<"Chieu dai cua chuoi = "<<strlen(strName)<< endl;
}
~CString()
{
delete []strName;
}
};
void main()
{
clrscr();
CString strFirst("Chao cac ban");
CString strSecond("Chao tam biet");
strFirst.Display();
strSecond.Display();
}
Và khi chương trình được chạy nó sẽ cho kết quả ở màn hình output như sau:
Trang 18
Lập trình hướng đối tượng với C++
char strTitle[20];
public:
CWords()
{
nNum = 0;
strcpy(strTitle," ");
}
void Display(int i)
{
nNum = i;
cout << "Tham so la " << nNum << endl;
cout << "Day khong phai la chuoi" << endl;
}
void Display(char c)
{
strTitle[0] = c;
cout << "Tham so la " << strTitle[0] << endl;
cout << "Day la mot ky tu" << endl;
}
void Display(char* str)
{
strcpy(strTitle,str);
cout << "Tham so la " << strTitle << endl;
cout << "Day la mot chuoi" << endl;
}
void Display(char* str,int i)
{
strcpy(strTitle,str);
nNum = i;
cout<<"Tham so la "<<strTitle<<"and"<<nNum<<endl;
cout << "Day la mot chuoi" << endl;
}
};
void main()
{
clrscr();
CWords X;
X.Display(120);
X.Display('A');
X.Display("String");
X.Display("String",10);
}
Khi biên dịch chương trình trên và thực hiện nó ta được kết quả như sau:
Tham so la 120
Day khong phai la chuoi
Tham so la A
Day la mot ky tu
Tham so la String
Day la mot chuoi
Trang 19
Lập trình hướng đối tượng với C++
Tham so la Stringand 10
Day la mot chuoi
Trong chương trình này lớp CWords được định nghĩa với một constructor và một hàm chồng
Display(). Trong hàm main, khai báo một đối tượng X thuộc lớp CWords và hàm Display của nó
được gọi với các tham số khác nhau.
Với các đối số được đưa vào trong hàm khác nhau đó nó sẽ tương ứng với từng hàm Display đã
được khai báo trong lớp. Với tham số nào thì sử dụng hàm có đối số tương ứng đó.
X.Display(120);
X.Display('A');
X.Display("String");
X.Display("String",10);
Như hàm Dislay được gọi đầu tiên là hàm chỉ có duy nhất một đối số kiểu int, còn hàm Display
gọi kế tiếp là hàm Display mà đối số của nó có kiểu char, tiếp theo đó là hàm có đối số kiểu con
trá char, còn hàm cuối cùng có hai đối số là kiểu chuổi và kiểu số nguyên.
Một hàm có thể được định nghĩa như là một hàm friend của một lớp để có thể truy cập các
thuộc tính private của lớp đó. Một constructor và destructor của một lớp không thể là một hàm
friend.
Trong chương trình dưới đây, chúng ta sẽ sử dụng một hàm friend để cộng hai biến kiểu float
thuộc về hai lớp khác nhau là Alpha và Beta. Hàm friend là một hình thức cầu nối giữa hai lớp
khác nhau để truy cập các thuộc tính private của 2 lớp này.
#include <iostream.h>
#include <conio.h>
class Beta;
class Alpha
{
private:
float X;
public:
Alpha()
{
X = 5.0;
}
friend float Init(Alpha,Beta);
};
class Beta
{
private:
float Y;
public:
Beta()
{
Y = 1.0;
}
friend float Init(Alpha,Beta);
};
Trang 20
Lập trình hướng đối tượng với C++
Bài 1: Viết một chương trình khai báo lớp CString, tương tự như lớp CString đã viết trong bài
nhưng thêm một số tính năng sau:
Hàm Overwrite
void Overwrite(int c,int nPos);
//thay thế ký tự thứ nPos trong chuỗi bằng ký tự c
void Overwrite(char* str,int nPos);
//thay thế ký các ký tự trong chuỗi strNam từ vị trí nPos đến vị trí (nPos +
//strlen(str) " 1) bằng chuỗi str;
Một hàm constructor mặc định với chuỗi strName là rỗng.
Hàm Insert cũng hai hàm giống như hàm Overwrite nhưng là chèn tại vị trí nPos.
Vd: Insert("c",2); AABB -> AcABB
Insert("CC",2); AABB -> ACCABB
Bài 2: Viết một chương trình khai báo hai lớp CCircle và CRectangle. Hai lớp này có một hàm
friend Area để tính tổng diện tích của hai hình này, hàm này được khai báo như sau:
friend int Area(CCircle,CRectangle);
Trang 21
Lập trình hướng đối tượng với C++
#include <iostream.h>
#include <string.h>
#include <conio.h>
class Converter
{
private:
char str[80];
public:
Converter()
{
strcpy(str,””);
}
Converter(char *s)
{
strcpy(str,s);
}
void display()
{
cout <<str<< endl;
}
Converter operator ++() //dạng tiền tố
{
return (strupr(str));
}
Converter operator ++(int) //Hậu tố
Trang 22
Lập trình hướng đối tượng với C++
{
Converter ss = str;
char *ptr = strupr(str);
strcpy (str, ptr);
return ss;
}
Converter operator -- () //dạng tiền tố
{
return (strlwr(str));
}
Converter operator --(int) //Hậu tố
{
Converter ss = str;
char *ptr = strlwr(str);
strcpy(str,ptr);
return ss;
}
};
void main()
{
clrscr();
Converter s1 = “changed to UPPERCASE”;
Converter s2 = “BACK TO LOWER CASE”;
Converter s3 = “that is all for now”;
Converter s4 = “ENDING ON A LOW NOTE”;
Converter s5;
int i, j;
++s1;
cout << “++s1 = “;
s1.display();
--s2;
cout<<”++s1 = “;
s2.display();
s5 = s3++;
cout << “Result of s5 = s3++ “<< endl << “s3 = “;
s3.display();
cout<<”s5 = “;
s5.display();
s4--;
cout<<”s4-- = “;
s4.display();
}
Kết quả trên màn hình là (nhấn tổ hợp phím Alt F5 để xem) :
Trang 23
Lập trình hướng đối tượng với C++
Trong chương trình trên chúng ta xây dựng lớp Converter có một thành phần dữ liệu là mảng ký
tự. Chúng ta khai báo file string.h để sử dụng các hàm chuẩn về chuỗi.
Chúng ta sử dụng các hàm chuẩn về chuỗi: strupr() để chuyển chuỗi ký tự thành chuỗi ký tự hoa,
strlwr() để chuyển các chuỗi ký tự thành các chuỗi ký tự thường.
Để trình biờn dịch phõn biệt được các toán tử ++, -- đứng trước hay là đứng sau, chúng ta sử dụng
có pháp sau:
#include <iostream.h>
#include <string.h>
#include <conio.h>
const SIZE = 80;
class CPhrase
{
private:
char str[SIZE];
public:
CPhrase() //constructors
{
Trang 24
Lập trình hướng đối tượng với C++
strcpy(str,””);
}
CPhrase(char *s)
{
strcpy(str,s);
}
void display()
{
cout<<str<<endl;
}
CPhrase operator +=(CPhrase aa) //overloaded +=
{
if (strlen(str) + strlen(aa.str)<SIZE)
{
strcat(str,aa.str);
return (*this);
}
else
{
cout<<”string is too long”;
return (*this);
}
}
};
void main()
{
clrscr();
CPhrase s1;
CPhrase s2 = “ Chao cac ban”;
s1+=s2;
s1.display();
s1 = “ Chuc suc khoe”;
CPhrase s3;
s3 = s1 += s2;
s3.display();
CPhrase s4;
CPhrase s5 = “ Xin moi vao”;
s4 = s2 += s5 += s5;
s4.display();
}
3. Lưu file với tên “danag412.cpp”
4. Dịch và chạy chương trình
Kết quả trên màn hình là (nhấn tổ hợp phím Alt F5 để xem) :
Trang 25
Lập trình hướng đối tượng với C++
Nếu bạn chỉ sử dụng lệnh đơn giản là s1 += s2; thì trong hàm không cần trả về giá trị.
Tuy nhiên để có được lệnh phức tạp hơn như s3 = s1 +=s2, s4 = s2 += s5 += s5 phải
có kiểu trả về.
4.2 Đa năng hoá toán tử gán và khởi tạo chép đối tượng
Xây dựng lớp CString như sau:
#include <iostream.h>
#include <string.h>
#include <conio.h>
class CString
{
private :
char* str;
public:
CString (char* s=””) //constructor
{
int size = strlen(s);
str = new char[size+1];
strcpy(str, s);
}
Trang 26
Lập trình hướng đối tượng với C++
cout <<”s1 = “;
s1.showstring();
CString s2(s1), s3;
s3 = s1;
cout << “s2 = “;
s2.showstring();
cout << “s3 = “;
s3.showstring();
CString s4 = s1;
cout << “s4 = “;
s4.showstring();
}
4.3 Chuyển đổi kiểu với kiểu người dùng định nghĩa
Chuyển đổi kiểu qua lại giữa kiểu cơ vản và kiểu đối tượng.
1.Tạo file mới
2.Gõ đoạn chương trình sau
#include <iostream.h>
#include <string.h>
#include <conio.h>
const SIZE = 80;
class CString
{
private:
char str[SIZE];
public:
CString ()
{
strcpy(str,””);
}
CString (char *s)
{
strcpy (str,s);
}
void getstr()
{
cout<< “Nhap vao chuoi: “;
cin >>str;
}
Trang 27
Lập trình hướng đối tượng với C++
void display()
{
cout <<str<<endl;
}
operator char*()
{
return (str);
}
};
void main()
{
clrscr();
CString s1;
char* p;
s1.getstr();
s1.display();
p = s1;
cout << “Chuoi p = “<<p <<endl;
char n[15] = “Chuoi moi”;
s1 = n;
s1.display();
}
p = s1;
gán cho con trá kiểu ký tự p đối tượng s1. Khi trình biờn dịch thấy vế phải của phép gán là đối
tượng và vế trái là con trá ký tự thì nó sử dụng hàm chuyển kiểu.
s1 = n;
lệnh này trình biờn dịch tự động gọi hàm khởi tạo có một tham số, nếu hàm khởi tạo không được
định nghĩa thì trình biờn dịch sẽ báo lỗi.
Trang 28
Lập trình hướng đối tượng với C++
Xây dựng lớp “ngày” có cài đặt các toán tử ++, -- để tăng lên, giảm xuống 1 ngày.
Trang 29
Lập trình hướng đối tượng với C++
#include <iostream.h>
#include <conio.h>
class vehicle
{
protected:
int wheels;
double weight;
public:
void initialise(int whls, double wght);
int get_wheels()
{
return wheels;
}
double get_weight()
{
return weight;
}
double wheel_loading()
{
return weight/wheels;
}
};
Trang 30
Lập trình hướng đối tượng với C++
double truck::efficiency()
{
return payload/(payload + weight);
}
void main()
{
clrscr();
vehicle bicycle;
bicycle.initialise(2,25);
cout << “Xe dap co “<<bicycle.get_wheels() << ”banh xe. \n”;
cout << “Khoi dong banh xe ”<< bicycle.wheel_loading()
<< “don vi khoi luong tren mot banh xe. \n”;
cout<<”Khoi luong cua xe la ”<<bicycle.get_weight()
<<”don vi khoi luong. \n\n”;
Trang 31
Lập trình hướng đối tượng với C++
car c;
c.initialise(4,1500.0,5);
cout<<”Chiec xe o to cho duoc “<<c.passengers()<<” hanh khach.\n”;
cout<<”Chiec xe o to nang “<<c.get_weight()
<<”don vi khoi luong.\n”;
cout<<”Khoi dong banh xe “<<c.wheel_loading()
<< “don vi khoi luong tren mot banh xe. \n\n”;
truck v;
v.initialise(18,7000.0);
v.init_truck(1,15000.0);
cout<<”Xe tai nang “<<v.get_weight()<<” don vi khoi luong.\n”;
cout<<”Su hieu qua cua xe: ”<< 100.0*v.efficiency()
<<” phan tram.\n”;
}
Trong chương trình trên lớp vehicle có hai thành phần dữ liệu có khai báo là protected, và
nhiều hàm có khai báo là public. Lớp vehicle là lớp cơ sở của hai lớp car và truck. Chúng ta
thấy trong hai lớp này có truy xuất đến lớp cơ sở.
a. Đa kế thừa.
Đa kế thừa được sử dụng khi một lớp muốn kế thừa từ nhiều lớp cơ sở.
Trang 32
Lập trình hướng đối tượng với C++
#include <iostream.h>
#include<iomanip.h>
#include<conio.h>
void person_data::getinfo()
{
cout << “Ten: “;
cin>> name;
cout<<”So: “;
cin>>roll_no;
cout<<”Gioi tinh(F/M) : “;
cin>> sex;
}
Trang 33
Lập trình hướng đối tượng với C++
void academics::getinfo()
{
cout<<”Ten khoa (BA/MBA/MCA etc)? “;
cin>>course_name;
cout<< “Hoc ky (1/2/3/...)? “;
cin>>semester;
cout<<”muc do (A,B,B+,B-..) ? ”;
cin>>grade;
}
void academics::display()
{
cout<<course_name<<”\t”;
cout<<semester<<”\t”;
cout<<grade<<”\t”;
}
void stud_scholarship::getinfo()
{
person_data::getinfo();
academics::getinfo();
cout<<”Su ho tro “;
cin>>amount;
}
void stud_scholarship::display()
{
person_data::display();
academics::display();
cout<<setprecision(2);
cout<<amount<<endl;
}
void main()
{
clrscr();
stud_scholarship obj;
cout<<”Nhap cac thong tin sau: “<<endl;
obj.getinfo();
cout<<endl;
cout<<”Ten So Gioi tinh Khoa Hoc ky Muc do”;
cout<<”Amount”<<endl;
obj.display();
}
Trang 34
Lập trình hướng đối tượng với C++
Trong chương trình trên, các lớp cơ sở có hàm trùng tên vì vậy khi lớp dẫn xuất gọi các hàm
này phải chỉ rõ là hàm dược gọi của lớp nào (xem hàm getinfo và hàm display của lớp dẫn
xuất).
#include<iostream.h>
#include<conio.h>
class Alpha
{
public:
Alpha()
{
cout<< “Ham khoi tao cua lop Alpha”<<endl;
}
};
Trang 35
Lập trình hướng đối tượng với C++
void main()
{
clrscr();
cout<<”Khai bao mot doi tuong cua lop Alpha \n”;
Alpha aa;
cout<<endl;
Trang 36
Lập trình hướng đối tượng với C++
Trang 37
Lập trình hướng đối tượng với C++
#include <iostream.h>
#include <string.h>
#include <conio.h.>
class person
{
protected:
char *name;
public:
person(char *n) { name = n;}
virtual void print() // hàm ảo
{
cout << “My name is :”<<name << endln;
}
};
class foreigner : public person
{
public:
foreigner(char *n) : person(n) { }
void printf()
{
cout <<ll mio nome e” <<name <<endln;
}
};
class alien : public person
Trang 38
Lập trình hướng đối tượng với C++
{
public:
alien(char *n) :person(n){ }
void print()
{
cout <<”&*^*&%& **^@<<name<<endln;
cout << sorry, there’s a communication problem”;
}
};
void main()
{
clrscr();
person* p1;
person *p2;
p1 = new person(“Jack”);
p2 = new foreigner(“Maria”);
cout <<”Introducing a Person:” <<endln;
p1->print();
cout <<”Introducing a Foreigner:” <<endln;
p2->print();
Trong vớ dụ trên ta thấy cả hai lớp dẫn xuất đều có hàm print như trong lớp cơ bản của
chúng, hàm print trong lớp person là một hàm ảo. Ban đầu cả hai con trá p1 và p2, p3 đếu
có kiểu person nhưng sau đó p1 lại thực sự trá đến một đối tượng kiểu person trong khi p2
lại trá đến một đối tượng kiểu foreigner và p3 trá đến đối tượng kiểu alien. Khi thực hiện
Trang 39
Lập trình hướng đối tượng với C++
p2 không gọi hàm print của lớp person mà gọi hàm print của lớp foreigner , và p3 gọi hàm
print của lớp alien. Đây chính là cơ chế đa hình mà ta đó nói ở trên.
6.3 Hàm thuần ảo.
Hàm thuần ảo là hàm ảo được mô tả bằng cách gán giá trị 0 cho hàm. Một lớp được gọi là
lớp trõu tượng nếu trong lớp tồn tại một hàm ảo và không thể dùng lớp này để định nghĩa một đối
tượng.
Xét chương trình sau:
#include <iostream.h>
#include <conio.h>
class format
{
public;
void display_form();
virtual void header()
{
cout << this is a header\n”;
}
virtual void body() = 0; // hàm thuần ảo
virtual void footer()
{
cout << “this is a footer\n\n”;
}
}
void Format :: display_form()
{
header();
for( int index = 0;index <3 ; index ++)
{
body();
}
footer();
};
void main()
{
clrscr();
Format* first_form = new MyForm;
First_form->display_form();
}
Trang 40
Lập trình hướng đối tượng với C++
~Base
Như vậy ta thấy chỉ có hàm hủy của lớp cơ bản được gọi , cũn hàm hủy của lớp dẫn xuất không
được gọi .
#include <iostream.h>
class Base
{
public:
virtual ~Base()
{
cout<<"~Base"<<endl;
}
Trang 41
Lập trình hướng đối tượng với C++
};
class Derived:public Base
{
public:
virtual ~Derived()
{
cout<<"~Derived"<<endl;
}
};
int main()
{
Base *B;
B = new Derived;
delete B;
return 0;
}
HINH
H_TRON H_CHUNHAT
Trong đó HINH là lớp cơ bản, H_TRON, H_CHUNHAT là các lớp dẩn xuất, lớp hình có
các hàm ảo thuần ảo
virtual void Ve() // hàm vẽ hình ra màn hình
virtual int TinhDienTich() // hàm tớnh diện tớch
Các lớp dẫn xuất sẽ viết lại các hàm trên để vẽ hay tính diện tích cho thích hợp.
Trang 42