2010-09-15 32 views
7

Khi thiết kế một API công khai, đó có phải là một cách hay để làm cho người xây dựng rõ ràng không?Có phải là một cách hay để làm cho người xây dựng rõ ràng

class A { 
public: 
    //explicit A(int i){} 
    A(int i){} 
}; 

void fun(const A& a) {} 

int main() { 
    // If I use explicit for A constructor, I can prevent this mistake. 
    // (Or shall I call it as feature?) 
    fun(10); 
} 

Hoặc tôi có cho phép chuyển đổi ngầm định, cho phép người dùng gọi API của tôi bằng cách nhập ít hơn không?

Trả lời

9

Nhà xây dựng phải rõ ràng, trừ khi chuyển đổi tiềm ẩn có ý nghĩa ngữ nghĩa (ví dụ: ý nghĩa của việc chuyển đổi int thành số A là gì?). Ít đánh máy không nên là tiêu chí để hướng dẫn quyết định đó. Hãy suy nghĩ về khả năng đọc (đó là đối số chính cho việc đúc ngầm) và mã của bạn là như thế nào để hiểu. Một diễn viên tiềm ẩn không trực quan sẽ làm cho người đọc mã bị trầy xước.

P.S .: Tôi dường như không thể đưa ra một ví dụ tốt ngay bây giờ, vì vậy mọi trợ giúp đều được đánh giá cao.

+7

ví dụ về chuyển đổi ẩn: bất kỳ điều gì giống số (ví dụ:thư viện bignum hoặc thư viện ngày/giờ) - chống lại chuyển đổi ngầm: chỉ xem xét lớp 'std :: vector' có thể được khởi tạo với kích thước ban đầu. –

+1

Tôi đồng ý với điều này. IME hiếm khi xảy ra trường hợp bạn muốn truyền ngầm và nếu bạn sai về mặt rõ ràng, không có hại gì được thực hiện bằng cách buộc người dùng phải thực hiện thêm một vài lần nhấn phím. – sbi

+0

Ví dụ: chuyển đổi ngầm từ đôi thành phức tạp thông qua 'phức tạp (double re, double im = 0)' có ý nghĩa, nhưng chuyển đổi từ int sang vector thông qua 'vector (int size)' thì không. –

1

Trình xây dựng rõ ràng được sử dụng trong các lớp, tiêu thụ tài nguyên quan trọng, như bộ nhớ, thời gian xây dựng, v.v., để ngăn người dùng tạo các trường hợp vô tình. Đó là vào bạn để quyết định, cho dù lớp học của bạn là "nặng", đủ để sử dụng constructor rõ ràng.

+5

Việc tạo ngẫu nhiên có thể gây tử vong ngay cả khi đối tượng không tốn kém. –

+0

@ Space_C0wb0y: tình cờ truyền là lỗi của riêng bạn khi vô tình nhập một dàn diễn viên. Chuyển đổi ngẫu nhiên ngầm là vấn đề ở đây, chắc chắn. –

+0

@Steve Jessop: Bạn đúng. –

1

Phụ thuộc vào chi phí có liên quan, cả ngữ nghĩa và hiệu suất. Nếu việc tạo ra lớp học của bạn là đắt tiền, bạn nên ngăn chặn nó được instantiated vô tình. Nếu đó là một lớp học rẻ tiền để tạo ra thì việc xây dựng ngầm có thể đơn giản hóa rất nhiều công việc cho người dùng API.

+1

Điều này không đề cập đến sự mơ hồ và các chuyển đổi không mong muốn, không có ý nghĩa có thể xảy ra. –

4

This là những gì tôi tìm thấy trong một resonse từ "Daniel Krügler"

Nếu chúng ta đã bắt đầu thiết kế C++ từ hôm nay trở đi, có một cơ hội tốt, rằng tất cả các nhà thầu và chức năng chuyển đổi được "rõ ràng" theo mặc định, nhưng người dùng có thể thực hiện "ẩn". Than ôi, thời gian không thể là quay lại và chúng tôi phải sống với trạng thái hiện tại. Điều này có nghĩa là chúng tôi phải cẩn thận đối với các nhà thầu tiềm ẩn (ngoại trừ các nhà xây dựng sao chép/di chuyển ). Đó là quy tắc an toàn hơn để làm cho nhà thầu rõ ràng, nơi một số hình thức chuyển đổi là tham gia (tức là bất kỳ nhà xây dựng nào với một loại đối số U khác với loại T thực tế).

+2

Daniel Krügler là ai? –

+0

@Yan Cheng CHEOK: Tôi đoán anh ấy là một phần của ủy ban tiêu chuẩn C++ (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010) – Chubsdad

5

Có, theo mặc định bất kỳ nhà xây dựng nào, có thể được gọi với một đối số phải rõ ràng. Theo quy tắc này sẽ tránh được các lỗi tinh vi, mà là cực kỳ khó tìm.

Tất nhiên, có những trường hợp ngoại lệ cho quy tắc này:

  • chuyển đổi ngầm có thể desireable, nếu lớp học của bạn có ngữ nghĩa của một wrapper xung quanh loại một trong những tham số của.

  • Sao chép trình xây dựng không được rõ ràng (nếu không bạn sẽ mất khả năng cho các cuộc gọi vượt qua giá trị).

+0

+1, nhưng sẽ thêm độ tin cậy nếu bạn minh họa cho biết lỗi. –

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