Tôi đang sử dụng shared_ptr và STL rộng rãi trong một dự án, và điều này dẫn đến quá lâu, các loại dễ bị lỗi như shared_ptr < vector < shared_ptr>> (Tôi là một lập trình viên ObjC bởi sở thích, nơi tên dài là tiêu chuẩn, và vẫn còn đây là quá nhiều.) Nó sẽ rõ ràng hơn nhiều, tôi tin rằng, để liên tục gọi FooListPtr này và ghi lại quy ước đặt tên là "Ptr" có nghĩa là shared_ptr và "List" có nghĩa là vector của shared_ptr.
để bắt đầu, tôi khuyên bạn nên sử dụng các cấu trúc thiết kế tốt cho phạm vi (ví dụ: không gian tên) cũng như các tên mô tả, không viết tắt cho typedef. FooListPtr
cực kỳ ngắn, imo. không ai muốn đoán những gì viết tắt có nghĩa là (hoặc ngạc nhiên khi tìm thấy Foo là const, chia sẻ, vv), và không ai muốn thay đổi mã của họ chỉ đơn giản là vì va chạm phạm vi.
cũng có thể giúp chọn tiền tố cho typedef trong thư viện của bạn (cũng như các danh mục phổ biến khác).
nó cũng là một ý tưởng tồi để kéo loại ra khỏi phạm vi tuyên bố của họ:
namespace MON {
namespace Diddy {
class Foo;
} /* << Diddy */
/*...*/
typedef Diddy::Foo Diddy_Foo;
} /* << MON */
có những ngoại lệ như sau:
- một kiểu riêng hoàn toàn ecapsualted
- một loại chứa trong một phạm vi mới
trong khi chúng tôi đang ở đó, using
trong phạm vi không gian tên và bí danh không gian tên cần tránh - đủ điều kiện phạm vi nếu bạn muốn giảm thiểu bảo trì trong tương lai.
Điều này rất dễ typedef, nhưng nó gây ra đau đầu với các tiêu đề. Dường như tôi có một số tùy chọn để xác định FooListPtr:
Foo.h. Điều đó bao gồm tất cả các tiêu đề và tạo ra các vấn đề xây dựng nghiêm trọng, do đó, nó không phải là một khởi đầu.
nó có thể là tùy chọn cho khai báo thực sự phụ thuộc vào các khai báo khác. ngụ ý rằng bạn cần chia các gói, hoặc có một giao diện chung, được bản địa hoá cho các hệ thống con.
FooFwd.h ("tiêu đề tiến lên"). Đây là những gì hiệu quả C++ cho thấy, dựa trên iosfwd.h. Nó rất nhất quán, nhưng chi phí của việc duy trì gấp đôi số lượng tiêu đề có vẻ gây phiền nhiễu nhất.
đừng lo lắng về việc duy trì điều này, thực sự. đó là một thực hành tốt. trình biên dịch sử dụng các khai báo về phía trước và typedef với rất ít nỗ lực. nó không gây phiền nhiễu vì nó giúp giảm sự phụ thuộc của bạn, và giúp đảm bảo rằng tất cả chúng đều chính xác và có thể nhìn thấy. có thực sự không phải là nhiều hơn để duy trì kể từ khi các tập tin khác đề cập đến tiêu đề 'loại gói'.
Common.h (đặt tất cả chúng lại với nhau thành một tệp). Điều này giết chết reusability bởi entwining rất nhiều loại không liên quan. Bây giờ bạn không thể chỉ nhận một đối tượng và di chuyển nó đến một dự án khác. Đó là một không khởi động.
gói phụ thuộc và bao gồm là tuyệt vời (lý tưởng, thực sự) - không loại trừ điều này. bạn rõ ràng sẽ phải tạo các giao diện gói (hoặc các thư viện) được thiết kế và cấu trúc tốt, và đại diện cho các lớp liên quan của các thành phần. bạn đang tạo ra một vấn đề không cần thiết trong việc tái sử dụng đối tượng/thành phần. giảm thiểu các dữ liệu tĩnh của một thư viện, và để cho các liên kết và các giai đoạn dải làm công việc của họ. một lần nữa, giữ cho các gói của bạn nhỏ và tái sử dụng và điều này sẽ không là một vấn đề (giả sử các thư viện/gói của bạn được thiết kế tốt).
Một số loại ma thuật #define ưa thích mà typedef nếu nó chưa được đánh máy. Tôi có một điều không thích hợp cho người tiền xử lý bởi vì tôi nghĩ rằng nó làm cho người mới khó có thể mò mẫm mã, nhưng có lẽ ...
thực sự, bạn có thể khai báo một kiểu gõ trong cùng phạm vi nhiều lần (ví dụ , trong hai tiêu đề riêng biệt) - đó không phải là lỗi.
tuyên bố typedef trong cùng phạm vi với các loại cơ bản khác nhau là lỗi. chắc chắn. bạn phải tránh điều này, và may mắn là trình biên dịch thực thi điều đó.
để tránh điều này, tạo 'bản dịch xây dựng' bao gồm cả thế giới - trình biên dịch sẽ gắn cờ khai báo các kiểu gõ không phù hợp.
cố gắng lén lút bằng typedef và số ít nhất là (hoặc đủ để giải phóng miễn phí) không đáng để thử. đôi khi bạn sẽ cần một loạt các hỗ trợ có điều kiện cho các tờ khai chuyển tiếp - một khi được xác định, nó rất dễ dàng (các thư viện stl là một ví dụ tốt về điều này - trong trường hợp bạn cũng đang chuyển tiếp khai báo template<typename,typename>class vector;
).
cách tốt nhất là chỉ cần có tất cả các khai báo này để xem bất kỳ lỗi nào ngay lập tức và bạn có thể tránh bộ tiền xử lý trong trường hợp này làm tiền thưởng.
Sử dụng phân lớp vectơ thay vì typedef. Điều này có vẻ nguy hiểm ...
một phân lớp của std::vector
thường được gắn cờ là "lỗi của người mới bắt đầu". vùng chứa này không có nghĩa là được phân lớp. không sử dụng các thực hành không tốt chỉ để giảm thời gian biên dịch/phụ thuộc của bạn.nếu phụ thuộc thực sự là có ý nghĩa, có lẽ bạn nên sử dụng pImpl, anyways:
// <package>.types.hpp
namespace MON {
class FooListPtr;
}
// FooListPtr.hpp
namespace MON {
class FooListPtr {
/* ... */
private:
shared_ptr< vector< shared_ptr<const Foo> > > d_data;
};
}
Có thực hành tốt nhất đây? Làm thế nào để họ bật ra trong mã thực, khi reusability, dễ đọc và nhất quán là tối thượng?
cuối cùng, tôi đã tìm thấy một gói ngắn gọn dựa trên phương pháp tiếp cận tốt nhất để sử dụng lại, để giảm thời gian biên dịch và giảm thiểu sự phụ thuộc.
Tôi có thể hỏi tại sao câu hỏi này là một wiki cộng đồng không? –
@Konrad, nếu có các đề xuất khác, tôi đã đề xuất thêm chúng vào danh sách để giúp người đọc sau này dễ dàng xem các tùy chọn khác biệt với câu trả lời về thành tích của họ. Có lẽ wiki cộng đồng được sử dụng khác nhau? –
Và sau nhiều nghiên cứu, tôi đã khám phá lại những gì tôi đã khám phá lần cuối khi tôi nhấp vào wiki cộng đồng, điều đó không có nghĩa là tôi làm điều đó ... Hy vọng tôi đã học được bài học của mình lần này. –