Các phương thức cđa lớp có thể được định nghĩa bên trong định nghĩa lớp hoặc bên ngoài định nghĩa lớp. Khi định nghĩa một phương thức bên ngoài định nghĩa lớp thì trước tên phương thức ta sử dụng Tên_lớp :: (Hai dấu hai chấm được gọi là toán tử phạm vi, nó xác định phương thức đang được định nghĩa là thành phần cđa lớp nào).
Ví dụ 2.2:
Định nghĩa phương thức display ở bên ngoài định nghĩa lớp point void point::display()
{
cout<<"Ham thanh phan displayn"; cout<<"Toa do: "<<x<<" "<<y<<"n";
}
2.3. Đối tượng
Đối tượng là một khái niệm trong lập trình hướng đối tượng biểu thị sự liên kết giữa dữ liệu và các hàm (gọi là các phương thức) thao tác trên dữ liệu đó. Ta có công thức sau:
Đối tượng = Dữ liệu + Phương thức
Có thể bạn quan tâm!
- Truyền Giá Trị Cho Hàm Theo Biến Tham Chiếu
- Lập trình hướng đối tượng - 4
- Lập trình hướng đối tượng - 5
- Lớp Không Có Hàm Tạo Và Hàm Tạo Mặc Định
- Lập trình hướng đối tượng - 8
- Hàm Tạo Và Đối Tượng Thành Phần
Xem toàn bộ 256 trang tài liệu này.
Đối tượng chính là công cụ hỗ trợ cho sự đóng gói. Sự đóng gói là cơ chề liên kết các lệnh thao tác và dữ liệu có liên quan, giúp cho cả hai được an toàn tránh được sự can thiệp từ bên ngoài và việc sử dụng sai.
2.3.1. biến, mảng đối tượng
Trong C++, một đối tượng có thể được xác lập thông quan một biến có kiểu lớp.
Một biến đối tượng được khai báo theo cú pháp: Tên_lớp Tên_biến;
Ví dụ: point A;
Để truy nhập vào thành phần cđa đối tượng thông qua biến đối tượng, ta sử dụng cú pháp: Tên_biến.Tên_thành_phần;
Ví dụ: A.x //truy nhập thuộc tính
A.display(); //truy nhập phương thức
Mảng đối tượng được khai báo như mảng thông thường, chỉ có điều kiểu dữ liệu ở đây là một lớp. Khi đó, mỗi phần tử mảng là một đối tượng.
Ví dụ point mang[100];
Để truy nhập vào thành phần cđa đối tượng thông qua mảng đối tượng, ta sử dụng cú pháp: Tên_biến_mảng[chỉ số phần tử].Tên_thành_phần;
Ví dụ: mang[4].x //truy nhập thuộc tính
mang[4].display(); //truy nhập phương thức
2.3.2. Con trỏ đối tượng
Con trỏ đối tượng được dùng để chứa địa chỉ cđa biến, mảng đối tượng. Nó được khai báo theo cú pháp: Tên_lớp*Con_trỏ;
Ví dụ: point *p;
Để truy nhập vào thành phần cđa đối tượng thông qua con trỏ đối tượng, ta sử dụng cú pháp: Con_tro->Tên_thành_phần;
Ví dụ: p->x //truy nhập thuộc tính
p->display(); //truy nhập phương thức
2.3.3. Đối cđa phương thức, con trỏ this
Con trỏ this là đối thứ nhất cđa phương thức, chính vì thề so với hàm tự do thực hiện cùng chức năng, phương thức cđa lớp bao giờ cũng có ít hơn hàm một đối kiểu con trỏ đối tượng cđa lớp. Đối này sẽ được xác định trong lời gọi phương thức đó.
Khi truy nhập vào các thuộc tính và phương thức cđa lớp có thể viết: this->tên_thuộc_tính hoặc chỉ cần viết tên_thuộc_tính.
Ví dụ 2.3:
#include <iostream.h>
#include <conio.h> class point
{
private: int x,y; public:
void nhap(); void hienthi();
};
void point::nhap();
{
cout<<” Nhap hoanh do:” ; cin>>this->x; //sử dụng this cout<<” Nhap tung do:” ; cin>>this->y; //sử dụng this
}
void point::hienthi();
{
cout<<” Toa do cua diem la: (“ <<x<<” ,” <<y<<” )” ; //không sử dụng this
}
void main()
{
clrscr(); point p;
p.nhap(); //lời gọi phương thức p.hienthi();
getch();
}
2.4. Hàm và các phương thức cđa lớp
2.4.1. Hàm và hàm bạn
Hàm
Hàm có tính chất sau:
Phạm vi hoạt động cđa hàm là trong toàn bộ chương trình. Tức là, hàm có thể
được gọi bất kỳ chỗ nào trong chương trình.
Đối (tham số) cđa hàm có thể là các đối tượng. Tuy nhiên, trong thân cđa hàm không thể truy nhập vào các thuộc tính riêng (private, protected) cđa đối tượng này.
Hàm bạn
Hàm bạn có tính chất sau:
Phạm vi hoạt động cđa hàm bạn là trong toàn bộ chương trình. Tức là, hàm bạn có thể được gọi bất kỳ chỗ nào trong chương trình.
Đối (tham số) cđa hàm bạn có thể là các đối tượng. Tuy nhiên, trong thân cđa hàm bạn cđa một lớp được phép truy nhập vào các thuộc tính cđa đối tượng cđa lớp này.
Lời gọi hàm bạn giống lời gọi cđa hàm thông thường
Hàm bạn cđa một lớp không phải là phương thức cđa lớp nên không có đối ngầm định là con trỏ this như phương thức cđa lớp
Một hàm có thể trở thành hàm bạn cđa nhiều lớp. Khi đó, hàm này có thể truy nhập vào tất cả các thuộc tính cđa các đối tượng cđa lớp mà nó là bạn.
Để một hàm trở thành hàm bạn cđa một lớp có 2 cách viết:
Cách 1: Dùng từ khoá friend để khai báo hàm trong khai báo lớp và xây dựng hàm bên ngoài lớp như các hàm thông thường. Mẫu cú pháp như sau:
class A
{
private:
//khai báo các thành phần riêng public:
//khai báo các thành phần dùng chung
friend Kiểu_trả_về Tên_hàm_bạn(Danh sách tham số);
.................
};
//Xây dựng hàm bên ngoài khai báo lớp Kiểu_trả_về Tên_hàm_bạn( Danh sách tham số)
{
// Thân cđa hàm bạn
}
Cách 2: Dùng từ khoá friend để xây dựng hàm ngay bên trong khai báo lớp. Mẫu cú pháp:
class A
{
private:
//khai báo các thành phần riêng public:
//khai báo các thành phần dùng chung
//Xây dựng hàm bên trong khai báo lớp
friend Kiểu_trả_về Tên_hàm_bạn( Danh sách tham số)
{
// Thân cđa hàm bạn
}
.................
};
Có nhiều kiểu bạn bè:
- Hàm tự do là bạn cđa một lớp.
- Hàm thành phần cđa một lớp là bạn cđa một lớp khác.
- Hàm bạn cđa nhiều lớp.
- Tất cả các hàm thành phần cđa một lớp là bạn cđa một lớp khác.
Hàm tự do bạn cđa một lớp
Trong hàm bạn, không còn tham số ngầm định this như trong hàm thành phần.
Hàm bạn cđa một lớp có thể có một hay nhiều tham số, hoặc có giá trị trả về thuộc kiểu lớp đó.
Hàm thành phần cđa lớp là bạn cđa lớp khác
Giả thiết có hai lớp A và B, trong B có một hàm thành phần f khai báo như sau: int f(char , A); nếu f có nhu cầu truy xuất vào các thành phần riêng cđa A thì f cần phải được khai báo là bạn cđa A ở trong lớp A bằng câu lệnh:
friend int B::f(char , A);
Để biên dịch được các khai báo cđa lớp A có chứa khai báo bạn bè kiểu như: friend int B::f(char, A);
chương trình dịch cần phải biết được nội dung cđa lớp B; nghĩa là khai báo cđa B (không nhất thiết định nghĩa cđa các hàm thành phần) phải được biên dịch trước khai báo cđa A. Ngược lại, khi biên dịch khai báo:
int f(char, A) ;
bên trong lớp B, chương trình dịch không nhất thiết phải biết chi tiềt nội dung cđa A, nó chỉ cần biết rằng A là một lớp. Để có được điều này ta dùng chỉ thị sau:
class A;
trước khai báo lớp B. Việc biên dịch định nghĩa hàm f cần các thông tin đầy đđ về các thành phần cđa A và B; như vậy các khai báo cđa A và B phải có trước định nghĩa đầy đđ cđa f. Tóm lại, sơ đồ khai báo và định nghĩa phải như sau:
class A; class B
{
...
int f(char, A);
...
};
class A
{
...
friend int B::f(char, A);
...
};
int B::f(char ...,A ...)
{
...
}
Hàm bạn cđa nhiều lớp
Mọi hàm (hàm tự do hay hàm thành phần) đều có thể là bạn cđa nhiều lớp khác nhau. Sau đây là một ví dụ một hàm là bạn cđa hai lớp A và B.
class B; class A
{
...
friend void f(A, B);
...
};
class B
{
...
friend void f(A,B);
...
};
void f(A...,B...)
{
//truy nhập vào các thành phần riêng cđa hai lớp bất kỳ A và B
}
Tất cả các hàm cđa lớp là bạn cđa lớp khác
Khi tất cả các hàm thành phần cđa một lớp là hàm bạn cđa một lớp khác ta có khái niệm lớp bạn, Chẳng hạn, tất cả các hàm thành phần cđa lớp B là bạn cđa lớp A thì khai báo trong lớp A chỉ thị:
friend class B;
thay vì phải khai báo tiêu đề cđa các hàm bạn là hàm thành phần cđa lớp B. class A
{
friend class B;
...
...
};
Ví dụ 2.4:
Chương trình minh hoạ việc sử dụng hàm bạn
#include<iostream.h>
#include<conio.h> int uscln(int a, int b)
{
while(a!=b) if(a>b) a=a-b; else b=b-a; return a;
}
class phanso
{
private: int ts; int ms; public:
void nhap()
{
cout<<"Tu so:";cin>>ts; cout<<"Mau so:";cin>>ms;
}
void hienthi();
friend phanso rutgon(phanso x)//hàm bạn
{
phanso kq; kq.ts=x.ts/uscln(x.ts,x.ms); kq.ms=x.ms/uscln(x.ts,x.ms);
return kq;
}
phanso operator+(phanso x); phanso operator-(phanso x); phanso operator*(phanso x); phanso operator/(phanso x);
};
void phanso::hienthi()
{
cout<<ts<<"/"<<ms;
}
phanso phanso::operator+(phanso x)
{
phanso kq; kq.ts=ts*x.ms+ms*x.ts; kq.ms=ms*x.ms;
return kq;
}
phanso phanso::operator-(phanso x)
{
phanso kq; kq.ts=ts*x.ms-ms*x.ts; kq.ms=ms*x.ms; return kq;
}
phanso phanso::operator*(phanso x)
{
phanso kq; kq.ts=ts*x.ts; kq.ms=ms*x.ms; return kq;
}
phanso phanso::operator/(phanso x)
{
phanso kq;