Lập trình

Lập trình

Thứ Tư, 2 tháng 12, 2015

Tìm hiểu về hàm tạo copy và toán tử gán - The copy constructor and overloading the assignment

The copy constructor and overloading the assignment

Trước hết ta cùng đến ví dụ assignment operator được sử dụng để sao chép giá trị từ một đối tượng đã khai bảo và đang tồn tại. Hãy nhớ kĩ "đã khai báo và đang tồn tại".
vd :

Test ob(5); // lệnh này gọi hàm tạo constructure của class Test
Test ob1; // lệnh này gọi hàm tạo mặc định của class
ob1 = ob; // gọi toán tử gán (assignment operator)

Ở trên vì ob1 đã được tạo trước khi toán tử gán được thực hiện nên nó sẽ gọi toán tử gán này.

Điều gì xảy khi sao chép giá trị đến một đối tượng chưa tồn tại ? Nó sẽ gọi constructure

Test ob(4);
Test ob1 = ob;

Nó như một cái nhà nếu chưa xây thì nó sẽ gọi copy constructor để khởi tạo ,lấy đồ về
còn nó đã được xây thì gọi toán tử lấy đồ về .

Mục đich của copy constructor và assignment operator là giống nhau cả hai đều copy dữ liệu từ một đối tượng đã tồn tại từ trước. Tuy nhiên toán tử gán sẽ copy dữ liệu đến một đối tượng đang tồn tại còn hàm tạo copy sẽ copy dữ liệu để khởi tạo đối tượng.

Có ba trường hợp sử dụng copy constructor thay vì assignment operator là :

1. Khi khai báo và nhanh chóng thiết lập một đối tượng từ đối tượng đã có
2. Khi tham sô truyền vào là tham trị
3. Khi một đối tượng được trả về trong hàm bằng kiểu giá trị

Có một lỗi sai gây run-time trong copy constructor đó là khi muốn copy dữ liệu từ đối tượng khác qua copy constructor nếu ta làm

nameClass(nameClass ob){
this->data = ob.data;
}

điều trên gây ra runtime vì khi một biến được truyền vào hàm thì bản thân hàm không dùng biến đó nó sẽ tạo ra một biến của riêng nó cùng kiểu nameClass và sao chép dữ liệu của ob vào , tất nhiên việc sao chép đó lại một lần nữa gọi copy constructor , cứ như vậy ... cho đến vô hạn. Điều này tương tự như đệ quy.Để xử lý điều này biến truyền vào là tham biến hoặc tham trỏ.

Một ví dụ về toán tử gán :
Cents& Cents::operator= (const Cents &cSource)
{
    // do the copy
    m_nCents = cSource.m_nCents;

    // return the existing object
    return *this;
}

như vậy khi ta
cMark = cNancy = cFred = cJoe; // assign cJoe to everyone

Cuối cùng một có một ví dụ đó là đối tượng tự gán cho chính nó

cMark = cMark; // valid assignment

Trong một vài trường hợp toán tử gán ko cần làm bất cứ thứ gì nhưng nếu class sử dụng cấp phát động thì nó rất nguy hiểm . Có một ý tưởng hay là kiểm tra xem nó có tự gán ko ngay ở đầu :

Cents& Cents::operator= (const Cents &cSource)
{
    // check for self-assignment by comparing the address of the
    // implicit object and the parameter
    if (this == &cSource)
        return *this;

    // do the copy
    m_nCents = cSource.m_nCents;

    // return the existing object
    return *this;
}

Ngoải ra còn có hàm copy mặc định do C++ cung cấp, kiểu đó còn gọi là shallow copy, bài này chúng ta sẽ tìm hiểu chi tiết sau.
Cảm ơn các bạn đã xem . :)

Không có nhận xét nào:

Đăng nhận xét