2010-04-03 32 views
16

Tôi có một dự án thú cưng mà tôi đã thử nghiệm với các tính năng mới của C++ 11. Trong khi tôi có kinh nghiệm với C, tôi khá mới với C++. Để rèn luyện bản thân mình thành các phương pháp hay nhất, (ngoài việc đọc nhiều), tôi đã bật một số tham số trình biên dịch nghiêm ngặt (sử dụng GCC 4.4.1):Tại sao enable_shared_from_this có một destructor không ảo?

-std=c++0x -Werror -Wall -Winline -Weffc++ -pedantic-errors 

Điều này đã làm việc tốt cho tôi. Cho đến bây giờ, tôi đã có thể giải quyết mọi trở ngại. Tuy nhiên, tôi có nhu cầu cho enable_shared_from_this và điều này gây ra sự cố cho tôi. Tôi nhận được cảnh báo sau (lỗi, trong trường hợp của tôi) khi biên dịch mã của tôi (có lẽ kích hoạt bởi -Weffc++):

base class ‘class std::enable_shared_from_this<Package>’ has a non-virtual destructor 

Vì vậy, về cơ bản, tôi là một chút nghe trộm bằng cách thực hiện này của enable_shared_from_this, bởi vì:

  • Trình phá hủy của lớp là nhằm mục đích cho phân lớp phải luôn là là ảo, IMHO.
  • Trình hủy không có gì, tại sao lại có nó?
  • Tôi không thể tưởng tượng bất kỳ ai muốn xóa cá thể của họ bằng cách tham chiếu đến enable_shared_from_this.

Nhưng tôi đang tìm cách để giải quyết vấn đề này, vì vậy câu hỏi của tôi thực sự là có cách thích hợp để giải quyết vấn đề này không? Và: tôi đúng khi nghĩ rằng destructor này là không có thật, hoặc là có một mục đích thực sự cho nó?

+1

Bạn đã thử kế thừa riêng tư hoặc được bảo vệ? Nó có thay đổi chẩn đoán không? – Tomek

+0

Đó là một ý tưởng tuyệt vời. Nhưng thật không may, nó không. –

+1

'-WeffC++' kích hoạt rất nhiều cảnh báo vô nghĩa (như liên quan đến thư viện) từ thư viện chuẩn, và điều này được đề cập trong [FAQ] (http://gcc.gnu.org/onlinedocs/libstdc++/faq.html # faq.wefcxx_verbose) –

Trả lời

23

Trình phá hủy của lớp dành cho phân lớp phải luôn là ảo, IMHO.

Trình phá hủy ảo trong lớp cơ sở chỉ cần thiết nếu một thể hiện của lớp dẫn xuất sẽ bị xóa qua con trỏ đến lớp cơ sở.

Có bất kỳ chức năng ảo nào trong một lớp, bao gồm cả trình phá hủy, yêu cầu trên cao. Boost (và thư viện chuẩn TR1 và C++ 11) không muốn ép buộc bạn có phí trên chỉ vì bạn cần có thể lấy một số shared_ptr từ con trỏ this.

Trình hủy không có gì, tại sao có nó?

Nếu bạn không có nhà xây dựng do người dùng xác định, trình biên dịch sẽ cung cấp cho bạn, vì vậy nó không thực sự quan trọng.

Tôi không thể tưởng tượng bất kỳ ai muốn xóa cá thể của họ bằng cách tham chiếu đến enable_shared_from_this.

Chính xác.

Đối với cảnh báo trình biên dịch, tôi sẽ bỏ qua cảnh báo hoặc ngăn chặn nó (với nhận xét trong mã giải thích lý do bạn làm như vậy). Thỉnh thoảng, đặc biệt là ở mức cảnh báo "pedantic", cảnh báo trình biên dịch là vô ích, và tôi muốn nói đây là một trong những trường hợp đó.

9

Tôi đồng ý với mô tả Jame, nhưng sẽ thêm

Một destructor ảo chỉ là cần thiết nếu bạn muốn tiêu diệt một thể hiện của lớp đó hầu. Đây không phải là luôn luôn như vậy, tuy nhiên nếu một lớp cơ sở không có ý định để bị phá hủy hầu như nó nên bảo vệ chống lại nó

Vì vậy, tôi sẽ thay đổi

Một destructor của lớp đó là dành cho subclassing nên luôn là là ảo, IMHO.

này là:

Một destructor của lớp đó là dành cho subclassing nên luôn ảo hoặc bảo vệ.

+0

Hmm .. điểm tốt. Hàm hủy của 'enable_shared_from_this' thực sự được bảo vệ. Vì vậy, có lẽ đây là một lỗi trong "-WeffC++" của GCC? –

+2

@ Shtééf: Hiệu quả C++ nói rằng các cơ sở đa hình nên có các dtors ảo, và các lớp không dành cho đa hình không nên có các dtors ảo. Kể từ khi trình biên dịch không thể nói đó là gì, tôi muốn nói rằng có nó là một lỗi để cung cấp cảnh báo này. Vì vậy, hoặc thực hiện của bạn IIRC lời khuyên về bảo vệ dtors trong các lớp cơ sở không đa hình nếu từ GotW/Exceptional C++, không hiệu quả. –

+2

Hơn nữa, phiên bản trang người đàn ông gcc của tôi nói rằng cảnh báo '-Wnon-virtual-dtor' chỉ dành cho các lớp có chức năng ảo. Vì vậy, hoặc 'enable_shared_from_this' có chức năng ảo (triển khai của tôi không), hoặc cảnh báo khác không tuân theo tài liệu (sẽ là lỗi), hoặc các tài liệu khác đã thay đổi (kiểm tra của bạn), có thể họ giải thích cảnh báo thêm nữa). Trên thực tế, có thể * Hiệu quả C++ * đã được cập nhật - trang người dùng gcc trích dẫn tiêu đề không khớp với ấn bản thứ 3 của tôi.Vì vậy, cho rằng đó là một lỗi trong cuốn sách của Scott Meyers ;-) –

4

có cách nào phù hợp để giải quyết vấn đề này không?

Không sử dụng -Weffc++ mọi lúc. Đôi khi bạn nên bật tính năng này để kiểm tra mã của mình nhưng không thực sự sử dụng nó vĩnh viễn. Nó mang lại những mặt tích cực sai và không thực sự được duy trì trong những ngày này. Sử dụng nó ngay bây giờ và sau đó, nhưng lưu ý bạn có thể phải bỏ qua một số cảnh báo. Lý tưởng nhất, chỉ cần học thuộc lòng tất cả những lời khuyên trong cuốn sách Meyers và sau đó bạn không cần nó anyway ;-)

là thích hợp trong suy nghĩ rằng destructor này là không có thật, hoặc là có một mục đích thực sự với nó?

Không, không phải là không có thật và có mục đích thực sự. Nếu nó không được xác định, nó sẽ được khai báo là public, để ngăn chặn nó được tuyên bố rõ ràng là protected.

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