Yêu cầu mọi thông tin sao chép từ blog này phải được ghi rõ đầy đủ: Thông tin được sao chép từ "http://www.dangngochoangthanh.blogspot.com".

Cool wallpaper http://www.fancymessage.com

EMOJI KEYBOARD PRO http://emojiselector.com

THƯ VIỆN HÌNH ĐỘNG FLASH ANIMATION: http://flashanimationlibrary.blogspot.ru/

Hệ thống học trực tuyến đang được phát triển và sẽ đưa vào sử dụng vào cuối năm nay. Hãy xem qua một số demo của Học Trực Tuyến.


HỌC TRỰC TUYẾN ĐÃ CUNG CẤP PHIÊN BẢN TRUY CẬP QUA MOBILE http://dangngochoangthanh.blogspot.com/?m=1

XEM KÊNH HỌC TRỰC TUYẾN TRÊN YOUTUBE



Search on This Blog

Saturday, September 11, 2010

Sao chép hàm tạo

Một đối tượng có thể được tạo ra từ hàm tạo theo cách khởi gán các dữ liệu thành viên của nó cho một giá trị nào đó. Bạn cũng hoàn toàn có thể khởi tạo một đối tượng từ một đối tượng khác. Khi thực thi điều này, trình biên dịch sẽ sao chép toàn bộ dữ liệu thành viên của đối tượng đó sang đối tượng khởi tạo của bạn. Cách thức sao chép này có thể là phép khởi gán trực tiếp từ đối tượng đã được khởi tạo sang đối tượng mới hoặc sao chép hàm tạo.


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);
Bạn lưu ý rằng, việc sao chép hàm tạo sẽ được quy định theo tham chiếu hằng const Humans&. Nếu bạn không viết hàm sao chép hàm tạo, thì trình biến dịch sẽ tự động làm giúp bạn (nghĩa là bạn luôn có thể sử dụng cách khởi tạo đối tượng theo kiểu Object newObj(oldObj); với oldObj là đối tượng thuộc lớp Object đã được tạo, dù bạn có tạo ra phương thức sao chép hàm tạo hay không). Hay nói cách khác, hàm tạo sao chép là mặc định đối với trình biên dịch GCC (kể cả Visual C++, Borland C++, Intel C++).

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

}

Bạn có thể thấy trong trường hợp không hợp lệ, bạn quy định đối tượng được tham chiếu m sẽ cho phép đối tượng khác tham chiếu đến nó theo tham chiếu hằng. Nhưng đối tượng tham chiếu đến nó, lại cố gắng thay đổi thuộc tính age của nó. Trong trường hợp này, chương trình sẽ phát sinh lỗi. Nếu bạn quy định là tham chiếu bình thường (bỏ đi từ khóa const) thì mọi việc sẽ bình thường.

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;

}

Trong trường hợp bạn muốn sử dụng phương thức cho đối tượng tham chiếu hằng, bạn cần khai báo phương thức GetTu và GetMau là phương thức hằng. Khi đó, bạn sử dụng cú pháp sau đây:

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;

}

Việc bổ sung từ khóa const vào sau khai báo phương thức sẽ giúp cho đối tượng tham chiếu hằng có thể gọi phương thức hằng này.

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();

}
Trong ví dụ này, chúng ta thấy các phương thức getter được khai báo là phương thức tham chiếu. Ta có thể gán trực tiếp giá trị cho các phương thức này. Trong trường hợp này, phương thức getter có cả hai tính năng: vừa là getter vừa là setter. Nhưng với tính năng của một phương thức setter đơn (tức chỉ thiết lập một giá trị duy nhất).

2 comments:

  1. 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 !!

    ReplyDelete
  2. Nế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