Lập trình hướng đối tượng - 2

Hàm tạo có nhiệm vụ khởi tạo một đối tượng: cấp phát bộ nhớ, gán các giá trị cho các thành phần dữ liệu cũng như việc chuẩn bị chỗ cho các đối tượng mới. Một lớp có thể có một hay nhiều hàm tạo. Để xác định hàm tạo nào cần gọi đến, chương trình biên dịch sẽ so sánh các đối số với các tham số truyền vào. Tương tự như hàm tạo, một lớp có thể có một hàm huỷ (destructor), một phương thức đặc biệt được gọi đến khi đối tượng được giải phóng khỏi bộ nhớ.

Lớp trong C++ thực chất là một kiểu dữ liệu do người sử dụng định nghĩa. Khái niệm định nghĩa chồng toán tử cho phép định nghĩa các phép toán trên một lớp giống như các kiểu dữ liệu chuẩn của C. Ví dụ chúng ta có thể định nghĩa một lớp số phức với các phép toán cộng, trừ, nhân, chia.

Cũng giống như C, C++ có khả năng chuyển đổi kiểu. Không những thế, C++ còn cho phép mở rộng sự chuyển đổi này sang các kiểu do người sử dụng tự định nghĩa (các lớp). Ví dụ, chúng ta có thể chuyển đổi từ kiểu chuẩn int của C sang kiểu số phức mà ta định nghĩa chẳng hạn.

C++ cho phép thực hiện thừa kế các lớp đã xây dựng. Từ phiên bản 2.0 trở đi, C++ còn cho phép một lớp thừa kế cùng một lúc từ nhiều lớp khác nhau (gọi là sự đa thừa kế).

Cuối cùng C++ cung cấp những thao tác vào ra mới dựa trên cơ sở khái niệm luồng dữ liệu (flow). Sự ưu việt của các thao tác này ở chỗ:

* Sử dụng đơn giản.

* Kích thước bộ nhớ được rút gọn.

* Khả năng áp dụng trên các kiểu do người sử dụng định nghĩa bằng cách sử dụng cơ chế định nghĩa chồng toán tử.

1.4.2. Lập trình cấu trúc và lập trình hướng đối tượng

Đặc trưng của lập trình hướng cấu trúc

Có thể bạn quan tâm!

Xem toàn bộ 256 trang tài liệu này.

Trong lập trình hướng cấu trúc, chương trình chính được chia nhỏ thành các chương trình con và mỗi chương trình con thực hiện một công việc xác định. Chương trình chính sẽ gọi đến chương trình con theo một giải thuật, hoặc một cấu trúc được xác định trong chương trình chính. Các ngôn ngữ lập trình cấu trúc phổ biến là Pascal, C và C++. Riêng C++ ngoài việc có đặc trưng của lập trình cấu trúc

do thừa kế từ C, còn có đặc trưng của lập trình hướng đối tượng. Cho nên C++ còn được gọi là ngôn ngữ lập trình nửa cấu trúc, nửa hướng đối tượng.

Lập trình hướng đối tượng - 2

Đặc trưng cơ bản nhất của lập trình cấu trúc thể hiện ở mối quan hệ: Chương trình = Cấu trúc dữ liệu + Giải thuật

Cấu trúc dữ liệu là cách tổ chức dữ liệu cho việc xử lý bởi một hay nhiều chương trình nào đó. Giải thuật là một quy trình để thực hiện một công việc xác định. Trong chương trình, giải thuật có quan hệ phụ thuộc vào cấu trúc dữ liệu: Một cấu trúc dữ liệu chỉ phù hợp với một số hạn chế các giải thuật. Nếu thay đổi cấu trúc dữ liệu thì phải thay đổi giải thuật cho phù hợp. Một giải thuật thường phải đi kèm với một cấu trúc dữ liệu nhất định.

Tính chất

Mỗi chương trình con có thể được gọi thực hiện nhiều lần trong một chương trình chính.

Các chương trình con có thể được gọi đến để thực hiện theo một thứ tự bất kì, tuỳ thuộc vào giải thuật trong chương trình chính mà không phụ thuộc vào thứ tự khai báo của các chương trình con.

Các ngôn ngữ lập trình cấu trúc cung cấp một số cấu trúc lệnh điều khiển chương trình.

Ưu điểm

Chương trình sáng sủa, dễ hiểu, dễ theo dòi.

Tư duy giải thuật rò ràng.

Nhược điểm

Lập trình cấu trúc không hỗ trợ mạnh việc sử dụng lại mã nguồn: Giải thuật luôn phụ thuộc chặt chẽ vào cấu trúc dữ liệu. Do đó, khi thay đổi cấu trúc dữ liệu, phải thay đổi giải thuật, nghĩa là phải viết lại chương trình.

Không phù hợp với các phần mềm lớn: tư duy cấu trúc với các giải thuật chỉ phù hợp với các bài toán nhỏ, nằm trong phạm vi một module của chương trình. Với dự án phần mềm lớn, lập trình cấu trúc tỏ ra không hiệu quả trong việc giải quyết mối quan hệ vĩ mô giữa các module của phần mềm.

Đặc trưng của lập trình hướng đối tượng

Trong lập trình hướng đối tượng:

Ta coi các thực thể trong chương trình là các đối tượng và sau đó trừu tượng hoá đối tượng thành lớp đối tượng.

Dữ liệu được tổ chức thành các thuộc tính của lớp. Nguời ta ngăn chặn việc thay đổi tuỳ tiện dữ liệu trong chương trình bằng các cách giới hạn truy nhập như chỉ cho phép truy nhập dữ liệu thông qua đối tượng, thông qua các phương thức mà đối tượng được cung cấp…

Quan hệ giữa các đối tượng là quan hệ ngang hàng hoặc quan hệ thừa kế: Nếu lớp B thừa kế từ lớp A thì A được gọi là lớp cơ sở và B được gọi là lớp dẫn xuất.

Lập trình hướng đối tượng có hai đặc trưng cơ bản:

Đóng gói dữ liệu: dữ liệu luôn được tổ chức thành các thuộc tính của lớp đối tượng. Việc truy nhập đến dữ liệu phải thông qua các phương thức của đối tượng lớp.

Sử dụng lại mã nguồn: việc sử dụng lại mã nguồn được thể hiện thông qua cơ chế thừa kế. Cơ chế này cho phép các lớp đối tượng có thể thừa kế từ các lớp đối tượng khác. Khi đó, trong các lớp dẫn xuất, có thể sử dụng các phương thức (mã nguồn) của các lớp cơ sở mà không cần phải định nghĩa lại.

Lập trình hướng đối tượng có một số ưu điểm nổi bật:

Không còn nguy cơ dữ liệu bị thay đổi tự do trong chương trình vì dữ liệu đã được đóng gói vào các đối tượng. Nếu muốn truy nhập vào dữ liệu phải thông qua các phương thức được cho phép của đối tượng.

Khi thay đổi cấu trúc dữ liệu của một đối tượng, không cần thay đổi mã nguồn của các đối tượng khác, mà chỉ cần thay đổi một số thành phần của đối tượng dẫn xuất. Điều này hạn chế sự ảnh hưởng xấu của việc thay đổi dữ liệu đến các đối tượng khác trong chương trình.

Có thể sử dụng lại mã nguồn, tiết kiệm tài nguyên, chi phí thời gian vì nguyên tắc thừa kế cho phép các lớp dẫn xuất sử dụng các phương thức từ lớp cơ sở như những phương thức của chính nó, mà không cần thiết phải định nghĩa lại.

Phù hợp với các dự án phần mềm lớn, phức tạp.


1.4.3. Cách viết dòng ghi chú

Trong một chương trình cần thiết có các lời chú thích, ngoài cách viết các lời chú thích như trong C, trong C++ ta sử dụng // để viết lời chú thích trên một dòng. Mọi

ký hiệu đi sau “//” cho đến hết dòng được coi là chú thích, được chương trình dịch bỏ qua khi biên dịch chương trình.

Ví dụ:

cin>>n; //nhap gia tri cho n tu ban phim


1.4.4. Khai báo linh hoạt và hằng có kiểu

Trong C++ không nhất thiết phải nhóm lên đầu các khai báo đặt bên trong một hàm hay một khối lệnh, mà có thể đặt xen kẽ với các lệnh xử lý.

Ví dụ 1.1:

#include<iostream.h>

#include<conio.h> void main()

{

int x,y;

cout<<Nhap so thu nhat:; cin>>x;

cout<<Nhap so thu hai:cin>>y;

int tong ; tong = x+y;

cout<<Tong hai so la:<<tong;

getch();

}

thậm chí ta có thể khai báo biến trong các khối lệnh if, for, while. Chẳng hạn như : for(int i = 1 ; i <= n ; i++)

Để tạo một hằng có kiểu sử dụng từ khoá const đặt trước một khai báo có khởi gán giá trị.

Ví dụ 1.2:

const int max= 100; struct Diem

{

int x,y;

};

const Diem d = {10, 10};

1.4.5. Các kiểu char và int

Trong C một hằng ký tự được xem là nguyên do đó nó có kích thước bằng 2 byte. Còn trong C++ một hằng ký tự được xem là giá trị kiểu char và có kích thước bằng một byte. Như vậy, trong C++ thì sizeof(A) = sizeof(char) = 1

1.4.6. Lấy địa chỉ các phần tử mảng thực hai chiều

Ngôn ngữ lập trình C không cho phép dùng toán tử & để lấy địa chỉ phần tử mảng thực hai chiều. Vì vậy, khi nhập giá trị cho phần tử mảng thực hai chiều phải sử dụng một biến phụ có kiểu thực. Trước tiên ta nhập giá trị cho biến phụ, sau đó, ta lấy giá trị biến phụ đó để gán cho phần tử mảng thực cần nhập.

Ví dụ 1.3:

trong C ta viết:

void nhap(float A[20][20], int n)

{

float x;

for(int i = 0; i < n; i++) for(int j = 0; j < n; j++)

{

printf(A[%d][%d] = ,i+1, j+1) scanf(%f, &x);

A[i,j] = x;

}

}

C++ cho phép lấy địa chỉ mảng thực hai chiều sử dụng toán tử &. Vì vậy, có thể dùng scanf để nhập trực tiếp vào các phần tử mảng.

void nhap(float A[20][20], int n)

{

for(int i = 0; i < n; i++) for(int j = 0; j < n; j++)

{

printf(A[%d][%d] = ,i+1, j+1)

scanf(%f, &A[i,j]);

}

}

1.4.7.Vào ra trong C++

Các hàm vào/ra của C đều có thể sử dụng trong C++. Để sử dụng các hàm này chúng ta chỉ cần khai báo tệp tiêu đề stdio.h trong đó có chứa khai báo hàm nguyên mẫu của chúng. Bên cạnh đó, C++ còn cài đặt thêm các khả năng vào/ra mới dựa trên hai toán tử “>>”(nhập) và “<<” (xuất) với các đặc tính sau đây:

- Đơn giản trong sử dụng

- Có khả năng mở rộng đối với các kiểu mới theo nhu cầu của người lập trình.

Trong tệp tiêu đề iostream.h người ta định nghĩa hai đối tượng cin và cout tương ứng với hai thiết bị chuẩn vào/ra được sử dụng cùng với “>>” và “<<”. Thông thường ta hiểu cout là màn hình còn cin là bàn phím.

Cú pháp của cout: cout<<biểu_thức_1<<biểu_thức_2<<…<<biểu_thức_n ;

trong đó các biểu thức có thể có kiểu là các kiểu dữ liệu như : char, int, float, double, xâu ký tự.

cout<<” n” ; dùng để xuống hàng và đưa con trỏ về đầu hàng

Nếu như cout dùng để hiển thị dữ liệu ra màn hình thì cin dùng để nhập dữ liệu từ bàn phím. Có thể sử dụng cin và toán tử “>>” để nhập dữ liệu cho các biến có kiểu char, int, float, double và char * như sau:

cin>>biến_1>>biến_2>>…>>biến_n; Ví dụ 1.4:

Chương trình sau nhập vào 2 số nguyên và in ra màn hình tổng của hai số đó

#include<iostream.h>

#include<conio.h> void main()

{

int so1,so2;

cout<<Nhap so thu nhat:; cin>>so1;

cout<<Nhap so thu hai:cin>>so2;

cout<<Tong hai so la:<<so1+so2; getch();

}

1.4.8. Cấu trúc trong C++

C++ vẫn chấp nhận khai báo kiểu cấu trúc như trong C. Ngoài ra, C++ còn cho phép khai báo kiểu cấu trúc theo cú pháp:

struct tên_kiểu

{

KiÓu_dl Tr•êng_1; KiÓu_dl Tr•êng_1; KiÓu_dl Tr•êng_1;

} ;

mµ kh«ng cÇn ph¶i sö dông tò kho¸ typedef nh• trong C. VÝ dô 1.5:

struct product

{

int weight; float price;

} ;

product apple;

product banana, melon;


1.4.9. Cấp phát bộ nhớ trong C++

Ngoài các hàm cấp phát bộ nhớ như malloc, realloc, calloc như trong C, C++ cung cấp toán tử new để cấp phát bộ nhớ và toán tử delete để giải phóng bộ nhớ được cấp phát bởi toán tử new.

Toán tử new thay thế cho hàm malloc() hay calloc() của C, có cú pháp như sau: new Kiểu_dữ_liệu

Nếu kiểu dữ liệu mô tả phức tạp, nó có thể được đặt bên trong các dấu ngoặc.

Nếu toán tử new cấp phát không thành công thì nó sẽ trả về giá trị NULL. Chúng ta có thể vừa cấp phát vừa khởi động như sau :

Con_trỏ = new Kiểu_dl(Giá_trị); Ví dụ 1.6:

int *P;

P = new int(100);

Toán tử delete thay thế hàm free() của C, nó có cú pháp như sau : delete Con_trỏ;

delete [] Con_trỏ;

Để cấp phát một mảng, chúng ta làm như sau : Con_trỏ = new Kiểu_dữ_liệu[Kích_thước_mảng] ;

Ví dụ 1.7: int *P;

P = new int[10]; //Cấp phát mảng 10 số nguyên

Chú ý: Đối với việc cấp phát mảng chúng ta không thể vừa cấp phát vừa khởi gán giá trị cho chúng, chẳng hạn đoạn chương trình sau là sai :

int *P;

P = new (int[10])(3); //Sai !!! Ví dụ 1.8:

Sử dụng kiểu cấu trúc, các toán tử new, delete trong việc cài đặt một số phép toán trên danh sách nối kép.

#include<iostream.h>

#include<conio.h>

struct node //khai bao cau truc mot nut trong ds noi kep

{

int info; node *lptr; node *rptr;

};

node *l,*r;

void create(int n)//t¹o lËp danh s¸ch nèi kÐp l•u tr÷ n sè nguyªn

{

node *p;int x; for(int i=1;i<=n;i++)

{

p=new node;

p->lptr=NULL; p->rptr=NULL;

cout<<"Nhap so nguyen:";cin>>p->info; if(l==NULL) l=r=p;

else

{

..... Xem trang tiếp theo?
⇦ Trang trước - Trang tiếp theo ⇨

Ngày đăng: 03/07/2022