Hàm bạn, lớp bạn (Friend function)
Giả sử có lớp Vector, lớp Matrix
Cần viết hàm nhân Vector với một Matrix
Hàm nhân:
Không thể thuộc lớp Vector
Không thể thuộc lớp Matrix
Không thể tự do
Giải pháp: Xây dựng hàm truy cập dữ liệu?
Hàm bạn không thuộc lớp. Tuy nhiên, có quyền truy cập các thành viên private của lớp.
Khi định nghĩa một lớp, có thể khai báo một hay nhiều hàm “bạn” (bên ngoài lớp)
Ưu điểm:
Kiểm soát các truy nhập ở cấp độ lớp – không thể áp đặt hàm bạn cho lớp nếu điều đó không được dự trù trước trong khai báo của lớp.
Dùng từ khóa friend để khai báo, định nghĩa hàm bạn
Đây là cách cho phép chia sẻ dữ liệu giữa các đối tượng với một hàm tùy ý trong chương trình (hàm friend) hoặc chia sẻ các thành phần của đối tượng có thuộc tính private hay protected với các đối tượng khác (lớp friend).
Các tính chất của quan hệ friend:
Phải được cho, không được nhận
Lớp B là bạn của lớp A, lớp A phải khai báo rõ ràng B là bạn của nó
Không đối xứng, Không bắc cầu
Quan hệ friend có vẻ như vi phạm khái niệm đóng gói (encapsulation) của OOP nhưng có khi lại cần đến nó để cài đặt các mối quan hệ giữa các lớp và khả năng đa năng hóa toán tử trên lớp (sẽ đề cập ở chương sau)
Ví dụ
class COUNTERCLASS{
int Counter;
public:
char CounterChar;
void Init( char );
void AddOne( ){
Counter++;
}
friend int Total (int);
};
COUNTERCLASS MyCounter[26]; //Có 26 đối tượng
int Total(int NumberObjects)
{
for (int i=0, sum=0; i<NumberObjects; i++)
sum += MyCounter[i].Counter
//Tính tổng số ký tự trong số các Objects ký tự
return sum;
}
Lưu ý:
Vị trí của khai báo “bạn bè” trong lớp hoàn toàn tùy ý
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ó thể có giá trị trả về thuộc kiểu lớp đó
Một lớp có thể truy cập đến các thành phần có thuộc tính private của một lớp khác.
Để thực hiện được điều này, chúng ta có thể lấy toàn bộ một lớp làm bạn (lớp friend) cho lớp khác.
Ví dụ
class TOM{
public:
friend class JERRY; //Có lớp bạn là JERRY
private:
int SecretTom; //Bí mật của TOM
};
class JERRY{
public:
void Change(TOM T){
T.SecretTom++; //Bạn nên có thể truy cập
}
};