Humans man(“Jack”, 21); //Sao chép trực tiếp Humans man2 = man; //Sao chép hàm tạo Humans::Humans(const Humans& m){ name = m.name; age = m.age; } Humans man2(man); |
Tham chiếu hằng. Phương thức sao chép hàm tạo (hoặc tổng quát là các phương thức có sử dụng tham chiếu hằng đến lớp đối tượng) có thể thực hiện theo tham chiếu hoặc tham chiếu hằng (tương ứng với không hoặc có từ khóa const), nhưng hãy luôn quy định là tham chiếu (có toán tử &). Khi quy định tham chiếu, địa chỉ của đối tượng này sẽ tham chiếu đến địa chỉ của đối tượng gốc. Giá trị của đối tượng tham chiếu sẽ được ánh xạ theo địa chỉ của đối tượng được tham chiếu (không thực hiện việc sao chép trực tiếp mà là gián tiếp thông qua địa chỉ của biến tham chiếu). Tuy nhiên, cũng vì lí do này mà đối tượng được tham chiếu có thể bị thay đổi giá trị (tương tự như truyền theo tham biến). Điều này làm vi phạm tính đóng gói trong lập trình hướng đối tượng. Cũng vì lí do này, C++ cung cấp cho ta từ khóa const để quy định một đối tượng khi được tham chiếu sẽ không bị làm thay đổi dữ liệu thành viên và nó được gọi là tham chiếu hằng. Như vậy, bạn cần phân biệt ba cách truyền tham số đối tượng trong một phương thức: truyền theo tham trị – dữ liệu của đối tượng có thể được thay đổi bên trong phương thức nhưng sự thay đổi này không lưu lại, việc sao chép dữ liệu trong trường hợp này là thực thi trực tiếp nên thường chỉ áp dụng cho các kiểu dữ liệu nguyên thủy đơn giản; truyền theo tham chiếu – dữ liệu của đối tượng có thể bị thay đổi trong phương thức và nó được lưu lại, nó thực hiện việc sao chép dữ liệu một cách gián tiếp nên dữ liệu có cấu trúc phức tạp (như lớp đối tượng, con trỏ) có thể được sao chép nhanh hơn rất nhiều so với truyền theo tham trị; tham chiếu hằng – tương tự như tham chiếu nhưng không cho phép thay đổi dữ liệu của đối tượng ngay cả trong phương thức.
Hợp lệ | Không hợp lệ |
… class Humans{ string name; int age; public: Humans(string, int); Humans(const Humans&); string getName(void); int getAge(void); }; Humans::Humans(const Humans& m){ name = m.name; age = m.age; } … | … class Humans{ string name; int age; public: Humans(string, int); Humans(const Humans&); ~Human(); string getName(void); int getAge(void); }; Humans::Humans(const Humans& m){ name = m.name; age = m.age = 22;//Error } … |
Khi một phương thức của lớp đối tượng sử dụng tham số là chính đối tượng của lớp đó, chúng ta có thể truy cập trực tiếp đến thuộc tính của đối tượng tham chiếu kể cả nó được quy định là private (cả tham chiếu lẫn không tham chiếu). Bên cạnh đó, nếu bạn quy định là tham chiếu bình thường, bạn còn có thể sử dụng các phương thức như getter và setter để truy cập đến các thuộc tính của nó. Nhưng nếu bạn sử dụng tham chiếu hằng, bạn không được phép truy cập đến các phương thức của đối tượng tham chiếu hằng. Bạn chỉ có thể truy cập đến các phương thức hằng của đối tượng tham chiếu hằng này. Phương thức hằng là những phương thức được bổ sung vào từ khóa const vào cuối khai báo phương thức trong tiêu đề hàm prototype và tiêu đề trong khai báo hàm đầy đủ. Bạn hãy quan sát các ví dụ sau đây.
Ví dụ Tham chiếu Hằng | Ví dụ Tham chiếu |
… class PhanSo { private: int Tu; int Mau; public: //Khai báo các hàm tạo PhanSo Nhan(const PhanSo&); int GetTu(void); int GetMau(void); }; PhanSo PhanSo::Nhan(const PhanSo& p) { return PhanSo(Tu*p.Tu, Mau*p.Mau); //không được phép viết PhanSo(Tu*p.GetTu(), Mau*p.GetMau()); } int PhanSo::GetTu(void) { return Tu; } int PhanSo::GetMau(void) { return Mau; } … | … class PhanSo { private: int Tu; int Mau; public: //Khai báo các hàm tạo PhanSo Nhan(PhanSo&); int GetTu(void); int GetMau(void); }; PhanSo PhanSo::Nhan(PhanSo& p) { return PhanSo(Tu*p.GetTu(), Mau*p.GetMau()); //hoặc PhanSo(Tu*p.Tu, Mau*p.Mau); } int PhanSo::GetTu(void) { return Tu; } int PhanSo::GetMau(void) { return Mau; } … |
int GetTu(void) const;
int GetMau(void) const;
… class PhanSo { private: int Tu; int Mau; public: //Khai báo các hàm tạo PhanSo Nhan(const PhanSo&); int GetTu(void) const; int GetMau(void) const; }; PhanSo PhanSo::Nhan(const PhanSo& p) { return PhanSo(Tu*p.Tu, Mau*p.Mau); //hoặc PhanSo(Tu*p.GetTu(), Mau*p.GetMau()); } int PhanSo::GetTu(void) const { return Tu; } int PhanSo::GetMau(void) const { return Mau; } … |
Thêm một khái niệm nữa trong C++ mà chúng ta cần biết là phương thức tham chiếu. Một phương thức tham chiếu cho phép ta sử dụng nó như một biến – bạn có thể gán trực tiếp một giá trị biến cho phương thức đó mà không gặp phải một trở ngại nào.
Chương trình |
#include <iostream> using namespace std; class complex{ private: float img; float real; public: complex(); complex(float, float); float &getimg(); float &getreal(); }; complex::complex( float img, float real ) { this->img = img; this->real = real; } complex::complex() { real = 0; img = 0; } float & complex::getreal() { return real; } float & complex::getimg() { return img; } int main () { complex c; c.getreal() = 2; c.getimg() = 1; cout<<c.getreal()<<" + I*"<<c.getimg(); } |
nội dung thì hay nhưng việc trình bày thì không đẹp, dễ làm nản người xem đấy !!
ReplyDeleteNếu muốn xem bản đầy đủ,bạn có thể xem trong giáo trình đính kèm trên blog này nhé
ReplyDelete