2012-01-14 43 views
5

Tôi có một lớp được gọi là Location và tôi cần thêm một CArray vào các biến thành viên của nó. Sự thay đổi này gây ra sự cần thiết phải quá tải toán tử gán.Toán tử gán chồng quá tải C++

Có cách nào để sao chép tất cả các biến trong loại lớp này đã được sao chép trước khi tôi thực hiện thay đổi và chỉ thêm mã bổ sung để sao chép CArray mà không sao chép từng biến thành viên riêng lẻ?

Location& Location::operator=(const Location &rhs) 
{ 
    // Only do assignment if RHS is a different object from this. 
    if (this != &rhs) 
    { 
     //Copy CArray 
     m_LocationsToSkip.Copy(rhs.m_LocationsToSkip); 

     //Copy rest of member variables 
     //I'd prefer not to do the following 
     var1 = rhs.var1; 
     var2 = rhs.var2; 
     //etc 
    } 

    return *this; 
} 
+0

Vì vậy, bạn muốn, có hiệu lực, gọi toán tử gán trình biên dịch tạo ra? 'CArray' có toán tử gán không? –

+0

Nó có một hàm tạo bản sao nhưng không có toán tử gán. Tôi không chắc chắn rằng tôi có thể gọi trình biên dịch tạo ra toán tử gán kể từ khi tôi đã thêm một biến thành viên CArray. –

+2

Không, bạn không thể gọi trình biên dịch được tạo ra bởi vì nó không được tạo ra nữa khi bạn cung cấp nó (không phải vì bạn đã thêm thành viên CArray, thứ duy nhất thay đổi là trình biên dịch tạo ra một cho lớp của bạn không thể gọi một cho CArray vì nó không tồn tại). Tôi sợ không có cách nào để làm điều này. –

Trả lời

4

Có, sắp xếp. Sử dụng loại quá tải operator= chính nó, do đó bạn không phải thực hiện việc đó trong lớp chứa. Ngay cả khi viết mã MFC, tôi vẫn chủ yếu sử dụng std::vector, std::string, v.v. thay vì tập hợp MFC và các lớp chuỗi. Đôi khi bạn bị kẹt khá nhiều khi sử dụng CString, nhưng tôi không thể nhớ lần cuối tôi đã sử dụng CArray thay vì std::vector.

+0

Tôi nghĩ đây là điều gần nhất với những gì tôi cần. Thật không may phần còn lại của ứng dụng sử dụng các container mfc và tôi ghét thay đổi điều này để sử dụng một container stl. Đây là một giải pháp tốt nếu không. Cảm ơn. –

0

Không, bạn không thể. Cách tốt nhất để làm điều này là sử dụng tập lệnh để tạo mã thực.

0

Điều này thường được thực hiện với những gì được gọi là "thành ngữ sao chép và hoán đổi". Bạn thực hiện một hàm tạo bản sao và một phương thức swap() trao đổi các giá trị thành viên và, quan trọng nhất là các con trỏ tới dữ liệu bên ngoài. Với nhà điều hành chuyển nhượng của bạn trông giống như:

C& C::operator=(const C& c) { 
    C tmp(c); 
    this->swap(tmp); 
    return *this; 
} 

Bạn thậm chí không cần bảo vệ tự gán với điều này.

+0

Nhưng bây giờ bạn phải liệt kê tất cả các thành viên trong việc thực hiện 'swap' của bạn. Điều này chỉ di chuyển vấn đề, nó không giải quyết nó. –

+0

Vâng, tôi không thấy vấn đề ở đây. Quá nhiều thành viên giá trị? Đóng gói chúng trong một cấu trúc và chỉ làm một nhiệm vụ nếu bạn đang đi cho ít gõ. –

2

Có. Những gì tôi thường làm là đặt mọi thứ vào cấu trúc Thành viên trong lớp ngoại trừ những gì không thể sao chép được. Như thế này:

class Location 
{ 
    struct Members 
    { 
     int var1, var2; 
    }; 

    Members m; 
    CArray m_LocationsToSkip; 

public: 
    Location& operator=(Location const& rhs); 
}; 

Location& Location::operator=(const Location &rhs) 
{ 
    // Only do assignment if RHS is a different object from this. 
    if (this != &rhs) 
    { 
     //Copy CArray 
     m_LocationsToSkip.Copy(rhs.m_LocationsToSkip); 

     //Copy rest of member variables 
     m = rhs.m; //will use Members automatically generated operator= 
        //which should do the correct thing because you only put 
        //normally copyable members in m 
    } 

    return *this; 
} 

đầu tiên tôi đăng tải về vấn đề này ở đây: https://stackoverflow.com/questions/469696/what-is-your-most-useful-c-c-utility/1609496#1609496

+0

Điều này có vẻ giống như một giải pháp phong nha nhưng nó sẽ mất khá nhiều refactoring trên phần còn lại của ứng dụng để hỗ trợ này. –

+0

@Cole W: làm thế nào? các thành viên của bạn được công khai và được sử dụng ở mọi nơi trong ứng dụng? Trong trường hợp đó, một lựa chọn khác là tạo một lớp quản lý tài nguyên để englobe CArray (một cách khác xung quanh ví dụ) để bạn có thể chỉ có một thành viên có thể cần tái cấu trúc (có thể không phụ thuộc vào cách nó được sử dụng). Tôi đã sử dụng ví dụ đó với cấu trúc vì đó là những gì tôi cần trong mã của tôi (đó là con trỏ, không phải mảng, và con trỏ thông minh không phải là thứ tôi cần) nhưng trong trường hợp của bạn, tạo lớp quản lý tài nguyên cho CArray là một lựa chọn tốt hơn. – n1ckp

Các vấn đề liên quan