2014-07-24 13 views
6

Tôi không thể hiểu lý do đằng sau việc bổ sung tự động các ctors mặc định. Đặc biệt, tôi thấy rất lúng túng khi mỗi lần tôi chỉ cần thêm một trình hủy ảo rỗng và không có gì nữa, tôi làm mất đi các thứ, nhưng thêm chúng tôi mất bản sao và các thứ mặc định, vì vậy tôi sẽ thêm tất cả đoạn mã này :Tại sao ctor di chuyển mặc định và gán không được trình biên dịch thêm vào khi một destructor được định nghĩa?

virtual ~SomeClass(){}   // you are the guilty! 
//virtual ~SomeClass() = default // would be the same 

SomeClass(SomeClass&&) = default;     // no more auto-added 
SomeClass& operator=(SomeClass&&) = default;  // no more auto-added 
SomeClass(const SomeClass&) = default;   // but with the moves defined, 
SomeClass& operator=(const SomeClass&) = default; // I'm now missing the copy 
SomeClass(){}          // and the default as well 

Tôi chắc chắn có lý do khiến lớp học của tôi xấu và cho phép tôi mong muốn macro xấu, tôi chỉ muốn biết cảm giác thoải mái hơn.

+0

Đó là cách nó chỉ định để hành xử. Xem ví dụ [tham chiếu này] (http://en.cppreference.com/w/cpp/language/move_constructor). –

+1

Thay vì thêm một dtor ảo mặc định hoặc rỗng, bạn có thể chỉ đơn giản là lấy được từ một lớp có một dtor ảo. 'struct make_polymorphic {virtual ~ make_polymorphic() = mặc định; }; '[Live example] (http://coliru.stacked-crooked.com/a/133459bcc0677b22) – dyp

+0

Hài hước. Khi tôi sử dụng các lớp đa hình (tức là với một destructor ảo), tôi có xu hướng không có bản sao hoặc di chuyển, bởi vì tôi cuối cùng sử dụng những thứ bằng cách tham khảo anyway. –

Trả lời

1

Hãy xem this. Nó giải thích một cái gì đó gọi là quy tắc của năm, mà về cơ bản là những gì tiêu chuẩn đòi hỏi.

Nói chung, đối với hầu hết các trường hợp, trình biên dịch tạo mặc định cho hàm tạo bản sao, gán bản sao, gán nhiệm vụ và hủy. Nhưng, nếu một lập trình viên định nghĩa bất kỳ cái nào trong số này, thì trình biên dịch giả sử người dùng đã đóng gói một cái gì đó trong lớp này đòi hỏi đặc biệt của anh ta/cô ấy, giả sử. destructor. Bây giờ lập trình viên biết rằng anh ta/cô ấy sẽ cần một destructor, trình biên dịch sẽ biết rằng lập trình viên biết những gì đang xảy ra và không tạo ra các giá trị mặc định cho phần còn lại (vì, dựa trên giả định rằng trình biên dịch tạo ra, mặc định những thứ sẽ sai, và thậm chí có thể dẫn đến hành vi không mong muốn).

+0

Nếu tôi chỉ cần gắn cờ destructor của tôi như ảo và không có gì nhiều hơn, trình biên dịch không nên gặp khó khăn khi đoán rằng tất cả các mặc định khác vẫn còn hiệu lực ... Tôi không thể tìm thấy một ví dụ về cái gì đó sẽ bị phá vỡ bởi điều này. – DarioP

+0

@DarioP có lẽ tôi đã quá muộn và bạn đã tiếp tục những điều tốt hơn, nhưng chỉ muốn chia sẻ bài viết này mà tôi đã xem qua hôm nay: [Để di chuyển hoặc không di chuyển] (http://www.stroustrup.com/ move.pdf) bởi B. Stroustrup. Ông nói về nhiều kịch bản giới thiệu một nhà điều hành di chuyển/sao chép mặc định có thể phá vỡ mọi thứ. Chỉ cần một đọc tốt tôi giả sử. –

0

Vấn đề là lớp của bạn đang cố gắng làm hai việc riêng biệt: cung cấp giao diện đa hình (do đó cần có trình phá hủy ảo) và quản lý thành viên dữ liệu cụ thể (do đó cần phải có hoạt động sao chép/di chuyển). Nó thường là một ý tưởng tốt để cung cấp cho mỗi lớp một trách nhiệm duy nhất.

Tôi muốn di chuyển trình phá hủy ảo và bất kỳ khai báo hàm ảo nào vào lớp cơ sở trừu tượng trống. Sau đó, bất kỳ lớp học cụ thể nào xuất phát từ đó sẽ được tự do phát sinh tất cả những thứ cần thiết.

Ví dụ:

#include <iostream> 

struct Movable { 
    Movable() {} 
    Movable(Movable&&m) {std::cout << "Moving\n";} 
}; 

struct SomeInterface { 
    virtual ~SomeInterface() {} 

    // no data members, so no need for any other special member functions 
}; 

struct SomeClass : SomeInterface { 
    Movable stuff; 

    // no user-declared special functions, so all are auto-generated 
}; 

int main() { 
    SomeClass c; 
    SomeClass c2(std::move(c)); // uses the auto-generated move constructor 
} 
+0

Cảm ơn bạn đã cung cấp giải pháp khác ngoài macro ác. Tôi vẫn không nhận được lý do ... tại sao các ctors sao chép mặc định vẫn được xác định khi tôi thêm destructor ảo của tôi? – DarioP

+0

@DarioP: Các hàm sao chép được tạo ngay cả khi có một destructor do người dùng khai báo vì đó là cách C++ luôn hoạt động và việc thay đổi sẽ phá vỡ nhiều mã hiện có. (C++ 11 không chấp nhận hành vi đó, nhưng không cấm nó).Di chuyển ngữ nghĩa là mới, do đó không bị ràng buộc bởi khả năng tương thích với các phương ngữ cũ hơn. –

+0

Điều đó có thực sự * không được chấp nhận * trong C++ 11 không? – DarioP

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