2013-04-15 42 views
5

Nếu một lớp không có một hàm tạo mặc định vì nó luôn luôn khởi tạo các biến nội bộ của nó, nó có làm theo nó không nên có một hàm khởi động di chuyển không?Không có hàm tạo mặc định nào không dẫn đến hàm tạo di chuyển không?

class Example final { 
public: 
    explicit Example(const std::string& string) : string_(
    string.empty() ? throw std::invalid_argument("string is empty") : string) {} 
    Example(const Example& other) : string_(other.string_) {} 
private: 
    Example() = delete; 
    Example(Example&& other) = delete; 
    Example& operator=(const Example& rhs) = delete; 
    Example& operator=(Example&& rhs) = delete; 
    const std::string string_; 
}; 

Lớp này luôn mong muốn chuỗi nội bộ được đặt bằng chuỗi không trống và chuỗi nội bộ được sao chép giữa các đối tượng Example. Tôi có chính xác rằng một nhà xây dựng di chuyển không áp dụng ở đây bởi vì nếu một ví dụ đã được di chuyển nó sẽ phải để lại chuỗi rỗng thông qua một cuộc gọi std::move?

+0

Vâng, miễn là * khách hàng * không thể tạo đối tượng trống (* "mặc định" *) khi chúng không được giả định, tại sao không * bạn * (chính thư viện) được phép làm như vậy. Tất nhiên không có vấn đề với một đối tượng mặc định bay xung quanh, miễn là khách hàng không thể trực tiếp xây dựng nó. Và nói chung, khách hàng không nên giả định bất cứ điều gì về việc chuyển từ đối tượng nào (ngoài việc nó có thể bị phá hủy và có thể được gán nhiều nhất). Họ không biết nó ở một số trạng thái mặc định (nếu không được ẩn), họ chỉ biết nó được di chuyển từ đó. –

+0

Tôi đoán, đây là những gì tôi nhận được tại: một khi bạn đã di chuyển một đối tượng, nó nên ở trong trạng thái nào? Tôi đã đọc rằng nó phải ở trạng thái 'hợp lệ', ví dụ, không có con trỏ lơ lửng, vv nhưng tôi đã luôn luôn triển khai các hàm khởi tạo 'move' khi rời khỏi đối tượng trong trạng thái mặc định để' move_object == Object() '. –

Trả lời

6

Nếu lớp không có hàm khởi tạo mặc định vì nó luôn khởi tạo biến nội bộ của nó, nó sẽ theo sau nó không nên có hàm khởi động?

Không, tôi sẽ không nói vậy.

Thực tế di chuyển từ đối tượng Example và để nó bằng chuỗi trống không phải là vấn đề ở đây, vì thường khách hàng không nên đưa ra giả định về trạng thái của đối tượng chuyển từ ngoài thực tế nó là hợp pháp.

Điều này có nghĩa là khách hàng chỉ có thể gọi các hàm không có điều kiện trước về trạng thái nhập Example của họ. Thông báo, thông thường, tất cả hầu hết tất cả các chức năng thành viên của Example sẽ có điều kiện trước về trạng thái của đối tượng (ví dụ: string_ phải là chuỗi không trống), nhưng không phải là chính xác tất cả trong số chúng. Ví dụ:

Ví dụ: trình phá hủy Example không nên phiền nếu string_ trống - tại sao nó không được phép thực hiện công việc ngay cả trong trường hợp đó? Toán tử gán là một ví dụ phổ biến khác - tại sao nó không được phép gán một chuỗi mới cho string_? Theo quan điểm này, để lại một đối tượng Example với một chuỗi rỗng là OK, bởi vì tất cả các khách hàng có thể làm với một đối tượng chuyển từ cơ bản hoặc gán lại hoặc hủy nó - và trong các trường hợp sử dụng này, nó nên không quan trọng là string_ có trống không.

Do đó, có hàm tạo di chuyển và toán tử gán di chuyển có ý nghĩa.

+0

Nó thực sự phụ thuộc vào những gì ông định nghĩa là trạng thái 'hợp lệ' cho đối tượng. Có một hàm tạo di chuyển vi phạm bất biến lớp không tốt, vì vậy nếu anh ta tài liệu như là một bất biến mà chuỗi không rỗng thì anh ta không nên có một hàm tạo di chuyển vi phạm điều đó. Tuy nhiên, điều đó không có nghĩa là anh ta không thể có một nhà xây dựng di chuyển, chỉ rằng nó nên duy trì bất biến, có lẽ sử dụng một giá trị chuỗi giả khi cần thiết. – bames53

+0

Cảm ơn câu trả lờ[email protected] bames53, bạn là chính xác trong đó lớp tôi có trong tâm trí không phải có một chuỗi rỗng, vì nó được sử dụng để vượt qua xung quanh 'con đường' vào một cái gì đó. Nếu 'Example' luôn đảm bảo rằng' string_' là một 'path' hợp lệ thì nó làm cho mọi thứ đơn giản hơn nhiều ở nhiều nơi bởi vì tôi không có các chuỗi đầu vào hợp lệ. Tuy nhiên, tôi đoán tôi có thể thực hiện một constructor 'move' và để lại' string_' trong trạng thái rỗng và chỉ cần kiểm tra điều kiện đó trong xác nhận hợp lệ. Các lớp tôi có trong tâm trí thực sự không xác nhận các chuỗi liên tục bằng cách sử dụng 'constexpr'. –

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