LINK DOWNLOAD MIỄN PHÍ TÀI LIỆU "Tài liệu Các khái niệm cơ sở của lập trình hướng đối tượng doc": http://123doc.vn/document/1035376-tai-lieu-cac-khai-niem-co-so-cua-lap-trinh-huong-doi-tuong-doc.htm
2. Tìm kiếm các đặc tính chung (dữ liệu chung) trong các dạng đối tượng này, những gì
chúng cùng nhau chia xẻ.
3. Xác định lớp cơ sở dựa trên cơ sở các đặc tính chung của các dạng đối tượng.
4. Từ lớp cơ sở, xây dựng các lớp dẫn xuất chứa các thành phần, những đặc tính không
chung còn lại của các dạng đối tượng. Ngoài ra, ta còn đưa ra các lớp có quan hệ với các lớp cơ
sở và lớp dẫn xuất.
1.4. Các ưu điểm của lập trình hướng đối tượng
Cách tiếp cận hướng đối tượng giải quyết được nhiều vấn đề tồn tại trong quá trình phát
triển phần mềm và tạo ra được những sản phẩm phần mềm có chất lượng cao. Những ưu điểm
chính của LTHĐT là:
1. Thông qua nguyên lý kế thừa, có thể loại bỏ được những đoạn chương trình lặp lại trong
quá trình mô tả các lớp và mở rộng khả năng sử dụng các lớp đã được xây dựng.
2. Chương trình được xây dựng từ những đơn thể (đối tượng) trao đổi với nhau nên việc
thiết kế và lập trình sẽ được thực hiện theo quy trình nhất định chứ không phải dựa vào kinh
nghiệm và kỹ thuật như trước. Điều này đảm bảo rút ngắn được thời gian xây dựng hệ thống và
tăng năng suất lao động.
3. Nguyên lý che giấu thông tin giúp người lập trình tạo ra được những chương trình an
toàn không bị thay bởi những đoạn chương trình khác.
4. Có thể xây dựng được ánh xạ các đối tượng của bài toán vào đối tượng của chương
trình.
5. Cách tiếp cận thiết kế đặt trọng tâm vào đối tượng, giúp chúng ta xây dựng được mô
hình chi tiết và gần với dạng cài đặt hơn.
6. Những hệ thống hướng đối tượng dễ mở rộng, nâng cấp thành những hệ lớn hơn.
7. Kỹ thuật truyền thông báo trong việc trao đổi thông tin giữa các đối tượng giúp cho việc
mô tả giao diện với các hệ thống bên ngoài trở nên đơn giản hơn.
8. Có thể quản lý được độ phức tạp của những sản phẩm phần mềm.
Không phải trong hệ thống hướng đối tượng nào cũng có tất cả các tính chất nêu trên. Khả
năng có các tính chất đó còn phụ thuộc vào lĩnh vực ứng dụng của dự án tin học và vào phương
pháp thực hiện của người phát triển phần mềm.
1.5. Các ngôn ngữ hướng đối tượng
Lập trình hướng đối tượng không là đặc quyền của một ngôn ngữ nào đặc biệt. Cũng giống
như lập trình có cấu trúc, những khái niệm trong lập trình hướng đối tượng có thể cài đặt trong
những ngôn ngữ lập trình như C hoặc Pascal, Tuy nhiên, đối với những chương trình lớn thì
vấn đề lập trình sẽ trở nên phức tạp. Những ngôn ngữ được thiết kế đặc biệt, hỗ trợ cho việc mô
tả, cài đặt các khái niệm của phương pháp hướng đối tượng được gọi chung là ngôn ngữ đối
tượng. Dựa vào khả năng đáp ứng các khái niệm về hướng đối tượng, ta có thể chia ra làm hai
loại:
1. Ngôn ngữ lập trình dựa trên đối tượng
2. Ngôn ngữ lập trình hướng đối tượng
Lập trình dựa trên đối tượng là kiểu lập trình hỗ trợ chính cho việc bao gói, che giấu thông
tin và định danh các đối tượng. Lập trình dựa trên đối tượng có những đặc tính sau:
• Bao gói dữ liệu
• Cơ chế che giấu và truy nhập dữ liệu
• Tự động tạo lập và xóa bỏ các đối tượng
• Phép toán tải bội
5
Ngôn ngữ hỗ trợ cho kiểu lập trình trên được gọi là ngôn ngữ lập trình dựa trên đối tượng.
Ngôn ngữ trong lớp này không hỗ trợ cho việc thực hiện kế thừa và liên kết động, chẳng hạn
Ada là ngôn ngữ lập trình dựa trên đối tượng.
Lập trình hướng đối tượng là kiểu lập trình dựa trên đối tượng và bổ sung thêm nhiều cấu
trúc để cài đặt những quan hệ về kế thừa và liên kết động. Vì vậy đặc tính của LTHĐT có thể
viết một cách ngắn gọn như sau:
Các đặc tính dựa trên đối tượng + kế thừa + liên kết động.
Ngôn ngữ hỗ trợ cho những đặc tính trên được gọi là ngôn ngữ LTHĐT, ví dụ như C++,
Smalltalk, Object Pascal v.v
Việc chọn một ngôn ngữ để cài đặt phần mềm phụ thuộc nhiều vào các đặc tính và yêu
cầu của bài toán ứng dụng, vào khả năng sử dụng lại của những chương trình đã có và vào tổ
chức của nhóm tham gia xây dựng phần mềm.
1.6. Một số ứng dụng của LTHĐT
LTHĐT đang được ứng dụng để phát triển phần mềm trong nhiều lĩnh vực khác nhau.
Trong số đó, có ứng dụng quan trọng và nổi tiếng nhất hiện nay là hệ điều hành Windows của
hãng Microsoft đã được phát triển dựa trên kỹ thuật LTHĐT. Một số những lĩnh vực ứng dụng
chính của kỹ thuật LTHĐT bao gồm:
+ Những hệ thống làm việc theo thời gian thực.
+ Trong lĩnh vực mô hình hóa hoặc mô phỏng các quá trình
+ Các cơ sở dữ liệu hướng đối tượng.
+ Những hệ siêu văn bản, multimedia
+ Lĩnh vực trí tuệ nhân tạo và các hệ chuyên gia.
+ Lập trình song song và mạng nơ-ron.
+ Những hệ tự động hóa văn phòng và trợ giúp quyết định.
CHƯƠNG 2
CÁC MỞ RỘNG CỦA NGÔN NGỮ C++
Chương 2 trình bày những vấn đề sau đây:
Giới thiệu chung về ngôn ngữ C++
Một số mở rộng của ngôn ngữ C++ so với ngôn ngữ C
Các đặc tính của C++ hỗ trợ lập trình hướng đối tượng
Vào ra trong C++
Cấp phát và giải phóng bộ nhớ
Biến tham chiếu, hằng tham chiếu
Truyền tham số cho hàm theo tham chiếu
Hàm trả về giá trị tham chiếu
Hàm với tham số có giá trị mặc định
Các hàm nội tuyến (inline)
Hàm tải bội
2.1. Giới thiệu chung về C++
C++ là ngôn ngữ lập trình hướng đối tượng và là sự mở rộng của ngôn ngữ C. Vì vậy mọi
khái niệm trong C đều dùng được trong C++. Phần lớn các chương trình C đều có thể chạy được
trong C++. Trong chương này chỉ tập trung giới thiệu những khái niệm, đặc tính mới của C++ hỗ
trợ cho lập trình hướng đối tượng. Một số kiến thức có trong C++ nhưng đã có trong ngôn ngữ
C sẽ không được trình bày lại ở đây.
6
2.2. Một số mở rộng của C++ so với C
2.2.1. Đặt lời chú thích
Ngoài kiểu chú thích trong C bằng /* */ , C++ đưa thêm một kiểu chú thích thứ hai, đó là
chú thích bắt đầu bằng //. Kiểu chú thích /* */ được dùng cho các khối chú thích lớn gồm nhiều
dòng, còn kiểu // được dùng cho các chú thích trên một dòng. Chương trình dịch sẽ bỏ qua tất cả
các chú thích trong chương trình.
Ví dụ: /* Đây là
câu chú thích trên nhiều dòng */
// Đây là chú thích trên một dòng
2.2.2. Khai báo biến
Trong C tất cả các câu lệnh khai báo biến, mảng cục bộ phải đặt tại đầu khối. Vì vậy vị trí
khai báo và vị trí sử dụng của biến có thể ở cách khá xa nhau, điều này gây khó khăn trong việc
kiểm soát chương trình. C++ đã khắc phục nhược điểm này bằng cách cho phép các lệnh khai
báo biến có thể đặt bất kỳ chỗ nào trong chương trình trước khi các biến được sử dụng. Phạm vi
hoạt động của các biến kiểu này là khối trong đó biến được khai báo.
Ví dụ 2.1 Chương trình sau đây nhập một dãy số thực rồi sắp xếp theo thứ tự tăng dần:
#include <stdio.h>
#include <conio.h>
#include <alloc.h>
void main()
{
int n;
printf("\n So phan tu cua day N=");
scanf("%d",&n);
float *x=(float*)malloc((n+1)*sizeof(float));
for (int i=0;i<n;i++)
{
printf("\n X[%d]=",i);
scanf("%f",x+i);
}
for(i=0;i<n-1;++i)
for (int j=i+1;j<n;++j)
if (x[i]>x[j])
{
float tg=x[i];
x[i]=x[j];
x[j]=tg;
}
printf("\n Day sau khi sap xep\n");
for (i=0;i<n;++i)
printf("%0.2f ",x[i]);
getch();
}
7
2.2.3. Phép chuyển kiểu bắt buộc
Ngoài phép chuyển kiểu bắt buộc được viết trong C theo cú pháp:
(kiểu) biểu thức
C++ còn sử dụng một phép chuyển kiểu mới như sau:
Kiểu(biểu thức)
Phép chuyển kiểu này có dạng như một hàm số chuyển kiểu đang được gọi. Cách chuyển kiểu
này thường được sử dụng trong thực tế.
Ví dụ 2.2 Chương trình sau đây tính sau tổng S =
n
1
3
1
2
1
1 ++++
Với n là một số nguyên dương nhập từ bàn phím.
#include <stdio.h>
#include <conio.h>
void main()
{
int n;
printf("\n So phan tu cua day N=");
scanf("%d",&n);
float s=0.0;
for (int i=1;i<=n;++i)
s+= float(1)/float(i); //chuyen kieu theo C++
printf("S=%0.2f",s);
getch();
}
2.2.4. Lấy địa chỉ các phần tử mảng thực 2 chiều
Trong C không cho phép dùng phép toán & để lấy địa chỉ của các phần tử mảng thực 2
chiều. Vì vậy khi nhập một ma trận thực (dùng hàm scanf()) ta phải nhập qua một biến trung
gian sau đó mới gán cho các phần tử mảng.
C++ cho phép dùng phép toán & để lấy địa chỉ các phần tử mảng thực 2 chiều, do đó thể
dùng hàm scanf() để nhập trực tiếp vào các phần tử mảng.
Ví dụ 2.3 Chương trình sau đây cho phép nhập một mảng thực cấp 20x20 và tìm các phần tử có
giá trị lớn nhất.
#include <conio.h>
#include <stdio.h>
void main()
{
float a[20][20],smax;
int m,n,i,j,imax,jmax;
clrscr();
puts(" Cho biet so hang va so cot cua ma tran: ");
scanf("%d%d",&m,&n);
for (i=0;i<m;++i)
for (j=0;j<n;++j)
{ printf("\n a[%d][%d]=",i,j);
scanf("%f",&a[i][j]);
8
}
smax=a[0][0];
imax=0;
jmax=0;
for (i=0;i<m;++i)
for(j=0;j<n;++j)
if(smax<a[i][j])
{
smax=a[i][j];
imax=i;
jmax=j;
}
puts("\n\n Ma tran");
for (i=0;i<m;++i)
for (j=0;j<n;++j)
{
if (j==0) puts("");
printf("%6.1f",a[i][j]);
}
puts("\n\n Phan tu max:");
printf("\n Co gia tri=%6.1f", smax);
printf("\n\n Tai hang %d cot %d",imax,jmax);
getch();
}
2.3. Vào ra trong C++
Để xuất dữ liệu ra màn hình và nhập dữ liệu từ bàn phím, trong C++ vẫn có thể dùng hàm
printf() và scanf(), ngoài ra trong C++ ta có thể dùng dòng xuất/nhập chuẩn để nhập/xuất dữ liệu
thông qua hai biến đối tượng của dòng (stream object) là cout và cin.
2.3.1. Xuất dữ liệu
Cú pháp: cout << biểu thức 1<<. . .<< biểu thức N;
Trong đó cout được định nghĩa trước như một đối tượng biểu diễn cho thiết bị xuất chuẩn của C+
+ là màn hình, cout được sử dụng kết hợp với toán tử chèn << để hiển thị giá trị các biểu thức 1,
2, , N ra màn hình.
2.3.2. Nhập dữ liệu
Cú pháp: cin >>biến 1>>. . . >>biến N;
Toán tử cin được định nghĩa trước như một đối tượng biểu diễn cho thiết bị vào chuẩn của C++
là bàn phím, cin được sử dụng kết hợp với toán tử trích >> để nhập dữ liệu từ bàn phím cho các
biến 1, 2, , N.
Chú ý:
• Để nhập một chuỗi không quá n ký tự và lưu vào mảng một chiều a (kiểu char) có thể dùng
hàm cin.get như sau: cin.get(a,n);
• Toán tử nhập cin>> sẽ để lại ký tự chuyển dòng ’\n’ trong bộ đệm. Ký tự này có thể làm trôi
phương thức cin.get. Để khắc phục tình trạng trên cần dùng phương thức cin.ignore(1) để bỏ
qua một ký tự chuyển dòng.
9
• Để sử dụng các loại toán tử và phương thức nói trên cần khai báo tập tin dẫn hướng
iostream.h
2.3.3. Định dạng khi in ra màn hình
• Để quy định số thực được hiển thị ra màn hình với p chữ số sau dấu chấm thập phân, ta sử
dụng đồng thời các hàm sau:
setiosflags(ios::showpoint); // Bật cờ hiệu showpoint(p)
setprecision(p);
Các hàm này cần đặt trong toán tử xuất như sau:
cout<<setiosflag(ios::showpoint)<<setprecision(p);
Câu lệnh trên sẽ có hiệu lực đối với tất cả các toán tử xuất tiếp theo cho đến khi gặp một
câu lệnh định dạng mới.
• Để quy định độ rộng tối thiểu để hiển thị là k vị trí cho giá trị (nguyên, thực, chuỗi) ta dùng
hàm: setw(k)
Hàm này cần đặt trong toán tử xuất và nó chỉ có hiệu lực cho một giá trị được in gần nhất.
Các giá trị in ra tiếp theo sẽ có độ rộng tối thiểu mặc định là 0, như vậy câu lệnh:
cout<<setw(6)<<“Khoa”<<“CNTT”
sẽ in ra chuỗi “ KhoaCNTT”.
Ví dụ 2.4 Chương trình sau cho phép nhập một danh sách không quá 100 thí sinh. Dữ liệu mỗi
thí sinh gồm họ tên, các điểm thi môn 1, môn 2, môn 3. Sau đó in danh sách thí sinh theo thứ tự
giảm dần của tổng điểm.
#include <iostream.h>
#include <conio.h>
#include <iomanip.h>
void main()
{
struct
{
char ht[25];
float d1,d2,d3,td;
}ts[100],tg;
int n,i,j;
clrscr();
cout << "So thi sinh:";
cin >> n;
for (i=0;i<n;++i)
{
cout << "\n Thi sinh:"<<i;
cout << "\n Ho ten:";
cin.ignore(1);
cin.get(ts[i].ht,25);
cout << "Diem cac mon thi :";
cin>>ts[i].d1>>ts[i].d2>>ts[i].d3;
ts[i].td=ts[i].d1+ts[i].d2+ts[i].d3;
}
10
for (i=0;i<n-1;++i)
for(j=i+1;j<n;++j)
if(ts[i].td<ts[j].td)
{
tg=ts[i];
ts[i]=ts[j];
ts[j]=tg;
}
cout<< "\ Danh sach thi sinh sau khi sap xep :";
for (i=0;i<n;++i)
{
cout<< "\n" << setw(25)<<ts[i].ht<<setw(5)<<ts[i].td;
}
getch();}
Ví dụ 2.5 Chương trình sau đây cho phép nhập một mảng thực cấp 50x50. Sau đó in ma trận
dưới dạng bảng và tìm một phần tử lớn nhất.
#include <iostream.h>
#include <iomanip.h>
#include <conio.h>
void main()
{
float a[50][50],smax;
int m,n,i,j,imax,jmax;
clrscr();
cout<< "Nhap so hang va cot:";
cin>>m>>n;
for (i=0;i<m;++i)
for (j=0;j<n;++j)
{
cout<< "a["<<i<<","<<j<<"]=";
cin>> a[i][j];
}
smax= a[0][0];
imax=0;
jmax=0;
for (i=0;i<m;++i)
for (j=0;j<n;++j)
if (smax<a[i][j])
{
smax=a[i][j];
imax=i;
jmax=j;
11
}
cout << "\n\n Mang da nhap";
cout << setiosflags(ios::showpoint)<<setprecision(1);
for (i=0;i<m;++i)
for (j=0;j<n;++j)
{
if (j==0) cout<<"\n";
cout << setw(6)<<a[i][j];
}
cout << "\n\n"<< "Phan tu max:"<< "\n";
cout << "co gia tri ="<<setw(6)<<smax;
cout<<"\nTai hang"<<imax<< " cot "<<jmax;
getch();
}
2.4. Cấp phát và giải phóng bộ nhớ
Trong C có thể sử dụng các hàm cấp phát bộ nhớ như malloc(), calloc() và hàm free() để
giải phóng bộ nhớ được cấp phát. C++ đưa thêm một cách thức mới để thực hiện việc cấp phát
và giải phóng bộ nhớ bằng cách dùng hai toán tử new và delete.
2.4.1. Toán tử new để cấp phát bộ nhớ
Toán tử new thay cho hàm malloc() và calloc() của C có cú pháp như sau:
new Tên kiểu ;
hoặc new (Tên kiểu);
Trong đó Tên kiểu là kiểu dữ liệu của biến con trỏ, nó có thể là: các kiểu dữ liệu chuẩn như int,
float, double, char, hoặc các kiểu do người lập trình định nghĩa như mảng, cấu trúc, lớp,
Chú ý: Để cấp phát bộ nhớ cho mảng một chiều, dùng cú pháp như sau:
Biến con trỏ = new kiểu[n];
Trong đó n là số nguyên dương xác định số phần tử của mảng.
Ví dụ: float *p = new float; //cấp phát bộ nhớ cho biến con trỏ p có kiểu int
int *a = new int[100]; //cấp phát bộ nhớ để lưu trữ mảng một chiều a
// gồm 100 phần tử
Khi sử dụng toán tử new để cấp phát bộ nhớ, nếu không đủ bộ nhớ để cấp phát, new sẽ trả
lại giá trị NULL cho con trỏ. Đoạn chương trình sau minh họa cách kiểm tra lỗi cấp phát bộ nhớ:
double *p;
int n;
cout<< “\n So phan tu : ”;
cin>>n;
p = new double[n]
if (p == NULL)
{
cout << “Loi cap phat bo nho”;
exit(0);
}
2.4.2. Toán tử delete
Toán tử delete thay cho hàm free() của C, nó có cú pháp như sau:
12
delete con trỏ ;
Ví dụ 2.6 Chương trình sau minh hoạ cách dùng new để cấp phát bộ nhớ chứa n thí sinh. Mỗi thí
sinh là một cấu trúc gồm các trường ht(họ tên), sobd(số báo danh), và td(tổng điểm). Chương
trình sẽ nhập n, cấp phát bộ nhớ chứa n thí sinh, kiểm tra lỗi cấp phát bộ nhớ, nhập n thí sinh, sắp
xếp thí sinh theo thứ tự giảm của tổng điểm, in danh sách thí sinh sau khi sắp xếp, giải phóng bộ
nhớ đã cấp phát.
#include <iomanip.h>
#include <iostream.h>
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
struct TS
{
char ht[20];
long sobd;
float td;
};
void main(void)
{
TS *ts;
int n;
cout<<"\nSo thi sinh n = ";
cin>>n;
ts = new TS[n+1];
if (ts == NULL)
{
cout << "\n Loi cap phat vung nho";
getch();
exit(0);
}
for (int i=0;i<n;++i)
{
cout << "\n Thi sinh thu "<<i;
cout<< "\n Ho ten";
cin.ignore(1);
cin.get (ts[i].ht,20);
cout << "so bao danh";
cin>> ts[i].sobd;
cout<< "tong diem:";
cin>>ts[i].td;
}
for (i=0;i<n-1;++i)
for (int j=i+1;j<n;++j)
if (ts[i].td<ts[j].td)
13
{
TS tg=ts[i];
ts[i]=ts[j];
ts[j]=tg;
}
cout << setiosflags(ios::showpoint)<<setprecision(1);
for (i=0;i<n;++i)
cout << "\n" << setw(20)<<ts[i].ht<<setw(6)<<ts[i].td;
delete ts;
getch();
}
2.5. Biến tham chiếu
Trong C có 2 loại biến là: Biến giá trị dùng để chứa dữ liệu (nguyên, thực, ký tự, ) và biến
con trỏ dùng để chứa địa chỉ. Các biến này đều được cung cấp bộ nhớ và có địa chỉ. C++ cho
phép sử dụng loại biến thứ ba là biến tham chiếu. Biến tham chiếu là một tên khác (bí danh) cho
biến đã định nghĩa trước đó. Cú pháp khai báo biến tham chiếu như sau:
Kiểu &Biến tham chiếu = Biến;
Biến tham chiếu có đặc điểm là nó được dùng làm bí danh cho một biến (kiểu giá trị) nào đó và
sử dụng vùng nhớ của biến này.
Ví dụ: Với câu lệnh: int a, &tong=a; thì tong là bí danh của biến a và biến tong dùng chung
vùng nhớ của biến a. Lúc này, trong mọi câu lệnh, viết a hay viết tong đều có ý nghĩa như nhau,
vì đều truy nhập đến cùng một vùng nhớ. Mọi sự thay đổi đối với biến tong đều ảnh hưởng đối
với biến a và ngược lại.
Ví dụ: int a, &tong = a;
tong =1; //a=1
cout<< tong; //in ra số 1
tong++; //a=2
++a; //a=3
cout<<tong; //in ra số 3
Chú ý:
• Trong khai báo biến tham chiếu phải chỉ rõ tham chiếu đến biến nào.
• Biến tham chiếu có thể tham chiếu đến một phần tử mảng, nhưng không cho phép khai
báo mảng tham chiếu.
• Biến tham chiếu có thể tham chiếu đến một hằng. Khi đó nó sử dụng vùng nhớ của hằng
và có thể làm thay đổi giá trị chứa trong vùng nhớ này.
• Biến tham chiếu thường được sử dụng làm đối của hàm để cho phép hàm truy nhập đến
các tham biến trong lời gọi hàm
2.6. Hằng tham chiếu
Cú pháp khai báo hằng tham chiếu như sau:
const Kiểu dữ liệu &Biến = Biến/Hằng;
Ví dụ: int n = 10;
const int &m = n;
const int &p = 123;
Hằng tham chiếu có thể tham chiếu đến một biến hoặc một hằng.
Chú ý:
14
Không có nhận xét nào:
Đăng nhận xét