Có lý do nào cho lớp triển khai được sử dụng trong thành ngữ pimpl để có bất kỳ thành viên riêng nào không? Lý do duy nhất tôi thực sự có thể nghĩ đến là tự bảo vệ bản thân - tức là các thành viên tư nhân phục vụ thực thi một số loại hợp đồng giữa lớp và người dùng, và trong trường hợp này, lớp và người dùng có quan hệ mật thiết hơn, vì vậy nó có vẻ không cần thiết.Thành viên riêng tư trong lớp học pimpl?
Trả lời
I nghĩ rằng mọi người đang bối rối Pimpl thành ngữ với Bộ điều hợp/Cầu/Chiến lược mẫu. Thành ngữ cụ thể cho một ngôn ngữ. Các mẫu có thể áp dụng cho nhiều ngôn ngữ.
Thành ngữ Pimpl được đưa ra để giải quyết vấn đề sau trong C++: Các thành viên riêng của một lớp được hiển thị trong khai báo lớp, điều này bổ sung thêm #include phụ thuộc không cần thiết cho người dùng của lớp. Thành ngữ này còn được gọi là tường lửa trình biên dịch.
Nếu thực hiện được ghi trực tiếp trong tệp * .cpp tương ứng của lớp bên ngoài và không thể truy cập bên ngoài mô-đun, thì Tôi nghĩ nó hoàn toàn ổn khi chỉ sử dụng cấu trúc cho lớp Pimpl. Tiếp tục tái thực thi ý tưởng cho rằng việc triển khai không có nghĩa là để được trực tiếp sử dụng lại, tôi xác định chúng như là một struct nội tin:
// foo.h
class Foo : boost::noncopyable
{
public:
...
private:
struct Impl;
boost::scoped_ptr<Impl> impl_;
};
// foo.cpp
struct Foo::Impl
{
// Impl method and member definitions
};
// Foo method definitions
Ngay sau khi có một tập tin tiêu đề cho lớp thực hiện, tôi nghĩ chúng ta không còn nói về thành ngữ Pimpl nữa. Chúng tôi đang nói về các lớp Adapter, Bridge, Strategy, giao diện, v.v ...
Chỉ 2 xu của tôi.
Tại sao không nên có các thành viên riêng tư? Chỉ vì bạn đang định nghĩa một giao diện vì PIMPL không có nghĩa là bạn sẽ không có thời gian nào khác muốn sử dụng lớp đó.
Vẫn là lớp học. Dữ liệu có thể là riêng tư hoặc được bảo vệ. Các hoạt động trên dữ liệu sẽ không bao giờ được truy cập công khai, riêng tư hoặc được bảo vệ. Các hoạt động mà bạn có thể muốn phơi bày, bảo vệ hoặc công khai.
Lý do chính của tôi vì không muốn các thành viên tư nhân là lười biếng tuyệt đối - tôi không muốn cung cấp cho người truy cập. Tôi nhận ra rằng cũng có thể có các thành viên cần riêng tư và không yêu cầu người truy cập. – Anne
Nó thực sự là một lớp "tư nhân" - chỉ có thể truy cập trong một tệp cpp. Cấu trúc kiểu C chỉ tốt cho mục đích trong hầu hết các trường hợp. –
Nemanja: Điều này giả định bên ngoài và bên trong được viết cùng một lúc. Tôi đã thêm pimpl sau khi thực tế để hiện thực hiện. –
Về lý thuyết, một lớp học pimpl vẫn chỉ là một lớp như bất kỳ lớp nào khác. Đó là việc triển khai thực hiện cụ thể một giao diện không có nghĩa là mã khác không phải là một ứng dụng khách của lớp pimpl.
Điều đó nói rằng, trong thực tế tôi đã thấy rằng các lớp pimpl có xu hướng gần gũi hơn với cấu trúc với một số hàm thành viên hơn là các đối tượng chính thức và ít cần tách giao diện khỏi triển khai.
Tùy thuộc vào việc triển khai pImpl của bạn - cụ thể là khi bạn thực thi bất biến lớp, nhưng nói chung tôi không cần phần impl để có các thành viên được bảo vệ/riêng tư. Trong thực tế, tôi thường tuyên bố nó như là một cấu trúc.
(Tôi hiểu lầm câu hỏi, vì vậy tôi thay đổi câu trả lời của tôi.)
Các lớp thực hiện, được trỏ đến bởi lớp với pimpl, phải là một lớp thông thường, với lý do cũng giống như nhiều để ẩn các chi tiết cá nhân như bất kỳ chi tiết nào khác. Trong thực tế, nó thường là một lớp có sẵn, với lớp pimpl được thêm vào sau để phá vỡ các phụ thuộc và có lẽ đơn giản hóa giao diện một chút.
Lớp đã tồn tại từ trước là lớp "bên ngoài", không phải là phần "impl". –
Tôi đã nhìn thấy nó đi cả hai cách. Đôi khi pimpl là một cách để đặt một giao diện nhất quán trên các triển khai có thể thay đổi. Các thời điểm khác, pimpl là một cách để ẩn hoàn toàn việc triển khai thực hiện, phá vỡ các phụ thuộc thời gian biên dịch. Trong thực tế, cả hai đều có thể là mục tiêu. –
Lý do duy nhất tôi thực sự có thể nghĩ đến là để bảo vệ mình khỏi chính mình
Đó là lý do tại sao "private" và "bảo vệ" đang có ở nơi đầu tiên. Tất nhiên bạn nên sử dụng chúng trong thực hiện của bạn - thời gian duy nhất tôi sẽ không được nếu việc thực hiện không có hành vi (trong trường hợp đó nó không thực sự là một thực hiện).
Vì private
có nghĩa là đóng gói dữ liệu tốt hơn.
Có vẻ như ngớ ngẩn, tôi biết, nhưng chúng ta có một cách để xác định các giao diện tại nơi làm việc đó là rất đơn giản:
class Interface;
class Concrete { public: .... private: Interface* m_interface; }
class ConcreteFoo: public Interface {};
Ưu điểm chính: bạn có thể trao đổi cho ConcreteBar
khác bất cứ lúc nào. Trên thực tế, sự kết hợp của mẫu Pimpl
và Strategy
và hàm tạo của Concrete
sẽ gọi số Factory
sẽ chịu trách nhiệm phân phối đối tượng hiệu quả.
Nếu bạn không thể nghĩ ra cách thứ hai để triển khai trái tim, hãy đóng gói nó trong một lớp học.Bằng cách này, nếu sau này bạn phải cấu trúc lại, bạn sẽ chỉ cần tạo một tập hợp trừu tượng Interface
với cùng một tập hợp phương pháp, thay đổi một vài con trỏ (và hàm khởi tạo) và bạn sẽ ổn thỏa;)
- 1. Lớp thành viên tĩnh - khai báo lớp riêng tư và lớp thành viên riêng tư?
- 2. Thành viên riêng tư trong CoffeeScript?
- 3. Các Thành viên Riêng tư trong R Lớp Tham chiếu
- 4. Thành viên lớp học "tĩnh"
- 5. Thành viên lớp học chung trong C#?
- 6. Ẩn các thành viên dữ liệu riêng tư? (C++)
- 7. Nối tiếp dữ liệu thành viên riêng tư
- 8. Tại sao chức năng bạn bè này không thể truy cập thành viên riêng tư của lớp học?
- 9. Làm thế nào để ẩn các thành viên tư nhân của một lớp học?
- 10. Cho phép một lớp "bạn" chỉ truy cập một số thành viên riêng tư
- 11. Làm cách nào để lớp học chỉ có thể truy cập một số thành viên riêng tư của một lớp học khác?
- 12. bạn bè có lớp học nhưng không thể truy cập thành viên riêng
- 13. const tham chiếu thành viên công khai cho thành viên lớp học tư nhân - tại sao nó hoạt động?
- 14. Thành viên lớp học Python Khởi tạo
- 15. Lớp học truy cập vào lớp học bên trong tư nhân?
- 16. cách truy cập vào các thành viên riêng tư của lớp lồng nhau?
- 17. Tại sao biến thành viên riêng tư có thể được thay đổi bởi cá thể lớp?
- 18. Truy cập các biến thành viên riêng tư từ một toán tử gán lớp khuôn mẫu
- 19. Thành viên lớp học mơ hồ trong vb.net
- 20. Biến tĩnh riêng tư trong lớp php
- 21. Lớp riêng tư trong không gian tên
- 22. Làm cách nào để kế thừa thành viên riêng tư trong JavaScript?
- 23. Tại sao xác định các thành viên riêng dưới các thành viên công khai trong C++?
- 24. Android: Đề xuất AsyncTask: lớp riêng tư hoặc lớp học công khai?
- 25. Tôi có thể đặt biến thành viên công khai ở chế độ riêng tư trong lớp học có nguồn gốc không?
- 26. Truy cập vào các thành viên riêng của một Superclass
- 27. pimpl cho một lớp templated
- 28. Các lớp học riêng và uml
- 29. C# ghi đè lên thành viên công khai và đặt thành riêng tư
- 30. Tại sao Visual Studio's intellisense hiển thị các thành viên và chức năng riêng tư?
Giả sử thực hiện gộp cho chuỗi chỉ đọc, lớp triển khai có thể rất có tính tham chiếu để biết khi nào cần giải phóng bộ nhớ, nếu được yêu cầu. – dirkgently
dirkgently: Tôi sẽ tưởng tượng rằng, để có một số duy nhất cho tất cả các tham chiếu đến một chuỗi, số đó sẽ phải được lưu trữ tập trung, trong chuỗi và không phải là trình bao bọc. Tôi đang thiếu gì ở đây? –
@Steven Sudit: Bởi vì nó sẽ vi phạm thiết kế - số lượng tham chiếu nghiêm túc nói không phải là một phần của cấu trúc dữ liệu cần thiết để đại diện cho chuỗi. – dirkgently