2011-07-07 29 views
7

Tôi thấy rằng việc tạo lớp không thể sao chép sẽ giúp tôi rất nhiều với chất lượng mã của tôi. Ban đầu tôi đã làm điều này với boost :: noncopyable, nhưng tôi thấy lỗi trình biên dịch VC++ không phải là hữu ích như với các thành viên cá nhân (nhấp đúp dẫn đến vị trí sai trong mã).C++ Không thể sao chép ngoại trừ đôi khi

T(T const&); 
T& operator=(T const&); 

Thật vậy, nó đã cảnh báo cho tôi một số trường hợp là các lớp không được chuyển làm tài liệu tham khảo mà họ nên có. Vì vậy, nhiều như vậy, rằng tôi rất muốn có được một cảnh báo ngay cả trên các lớp học mà tôi chỉ cần sao chép xây dựng một lần.

Có cách nào tốt để thực hiện việc này không? Tôi đã suy nghĩ ví dụ để lại trên hai phương pháp riêng và thêm một công T (T const &, bool dummy) constructor để gọi khi tôi thực sự muốn sao chép xây dựng. Hoặc có thể cách khác làm cho trên hai phương pháp công khai và bằng cách nào đó kích hoạt một cảnh báo trình biên dịch khi xây dựng bản sao, ngăn chặn các cảnh báo mà tôi muốn.

Hoặc có thể có một cách tốt hơn?

Trả lời

6

Không chắc chắn nếu đó là chính xác những gì bạn muốn, nhưng nếu bạn đánh dấu nhà xây dựng bản sao explicit thì lớp không thể được truyền theo giá trị hoặc sao chép-khởi tạo, nhưng bạn có thể sao chép-xây dựng bằng cách khởi tạo trực tiếp.

Có thể bạn muốn giữ cho toán tử gán riêng tư, có thể cơ sở NonAssignable sẽ hữu ích cho điều đó.

+1

Tôi thích câu trả lời này tốt nhất. Vấn đề với các nhà xây dựng bản sao, theo kinh nghiệm của tôi, là khi họ được gọi "vô tình" trên một số đối tượng khổng lồ. '' rõ ràng buộc bạn phải suy nghĩ về nó khi bạn gọi chúng, điều này là đủ. – Nemo

+0

Chúc mừng, điều này hoàn toàn phù hợp với nhu cầu của tôi. Cảm ơn. – Cookie

2

Tôi nghĩ bạn đã đặt tên cho mình một cách hoàn hảo.

Tôi chỉ nhớ một gọn gàng chút lừa tôi một lần chơi trong một cơ sở mã tôi đã làm việc trên (?):

struct T 
{ 
    friend class SomeClientThatCanConstructT; 
    T(T const&); 

    private: 
    T(T const&);   
}; 

Như đã thảo luận trong các ý kiến ​​sau đây sẽ không bay

Bạn có thể chọn một tên rõ ràng (như CopyConstruct) và dựa vào RVO để có hiệu quả như nhau:

struct T 
{ 
    inline T CopyConstruct() const  { return *this; } 
    inline T& AssignTo(T& dst) const { return dst = *this; } 
    inline T& AssignFrom(const T& src) { return *this = src; } 

    private: 
    T(T const&); 
    T& operator=(T const&); 
}; 

+0

Tôi đã nghĩ về điều này nhưng 'CopyConstruct' của bạn yêu cầu rằng trình tạo bản sao có thể truy cập được ngay cả khi trình biên dịch không gọi nó. –

+0

Shute. Cảm ơn vì đã nhắc tôi. Điều này thực sự là một stopper. Tất nhiên bạn có thể làm hỏng nó tất cả các cách, nhưng đối với các cuộc gọi constructor, có thực sự là không có thay thế cho giải pháp 'tham số thẻ' của bạn. Nghĩ lại thì, tôi chợt nhớ mình tự mình làm việc này ...Cập nhật câu trả lời – sehe

+0

Bit của người bạn đó dường như thực hiện thủ thuật ngay bây giờ. –

0

Bạn có thể có thể mặc định xây dựng một T và sau đó thêm một phương pháp assign để sử dụng. Điều này dường như không hoàn toàn tối ưu mặc dù, chỉ ra rằng bạn có thể muốn xem lại nhu cầu sao chép của bạn.

0

Tôi không thích ý tưởng hạn chế một loại (CopyConstructible là một khái niệm được sử dụng nhiều trong suốt stdlib) vì nó có thể bị lạm dụng. Nếu bạn có thể xây dựng một đối tượng từ một thể hiện khác, nó sẽ được sao chép có thể xây dựng được. Nó cũng làm sao lãng người đọc khỏi mã quan trọng mà không phục vụ bất kỳ mục đích thực sự nào.

Có thể một cảnh báo hoặc xác nhận trong chế độ gỡ lỗi được kích hoạt bởi hàm tạo bản sao thực sự là những gì bạn đang tìm kiếm?

+0

Có điều gì không? ví dụ. thế nào tôi có thể xác định một cảnh báo người dùng định nghĩa bất cứ khi nào trình biên dịch hoặc liên kết liên kết đến một chức năng? và sau đó ngăn chặn cảnh báo trong tập tin đối tượng tôi muốn? Giống như một cảnh báo pragma vô hiệu hóa? – Cookie

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