2010-03-01 31 views
10

Loại thủ thuật nào có thể được sử dụng để giảm thiểu khối lượng công việc của việc triển khai các lớp pImpl?Thực hiện pImpl với số lượng mã tối thiểu

Tiêu đề:

class Foo { 
    struct Impl; 
    boost::scoped_ptr<Impl> self; 
public: 
    Foo(int arg); 
    ~Foo(); 
    // Public member functions go here 
}; 

Thực hiện:

struct Foo::Impl { 
    Impl(int arg): something(arg) {} 
    // All data members and private functions go here 
}; 

Foo::Foo(int arg): self(new Impl(arg)) {} 
Foo::~Foo() {} 

// Foo's public functions go here (and they refer to data as self->something) 

Làm thế nào bạn sẽ cải thiện điều này, sử dụng Boost, có thể thừa kế, CRTP hoặc thủ đoạn khác để tránh càng nhiều mã boilerplate càng tốt? Hiệu suất thời gian chạy không phải là một vấn đề.

+3

Trên thực tế, điều đó không thực hiện thành ngữ pimpl hoặc vì bạn chưa cố định constructor sao chép và phân công bản sao ' operator = 'trong Foo. –

+1

Tôi thường không cần copyability (và scoped_ptr theo mặc định cung cấp noncopyability), nhưng bạn có một điểm, việc tạo ra các chức năng có thể được tự động là tốt. – Tronic

Trả lời

5

Triển khai pimpl từ Loki có thể là câu trả lời hay. Xem thêm DDJ Article về điều này.

+0

Tôi đoán đây là một điều tốt ... – Tronic

1

Có thể, nhưng thực hiện ngây thơ không phải là những gì bạn muốn.

Vấn đề là các mẫu thường được sắp xếp theo hàng thực hiện ngây thơ sẽ là:

template <class Object> 
class Pimpl 
{ 
public: 
    explicit Pimpl(Object* obj): mObject(obj) {} 
    ~Pimpl() { delete mObject; } 

    // either deep copy or no copy 
private: 
    Object* mObject; 
}; 

Bây giờ vấn đề là bạn không muốn Object được biết đến trong tập tin tiêu đề của bạn nói chung (không cho nhị phân khả năng tương thích, nhưng đối với quản lý phụ thuộc). Và nếu không biết Object thì bạn không thể triển khai trực tiếp các số Destructor, Copy ConstructorAssignment Operator ...

Sự cố vẫn chưa được giải quyết! Boost thực sự đã giải quyết nó cho shared_ptr.

Ý tưởng là chuyển một mục thứ hai trong hàm khởi tạo, sẽ xử lý bộ nhớ đầu tiên và sẽ được cung cấp thực thi mặc định tốt đẹp.

Điều này làm việc với một hướng dẫn, tất nhiên.

namespace detail { 
    template <class Object> 
    struct Deleter { virtual void do(Object*) = 0; }; 
} 

template <class Object> 
class Pimpl 
{ 
public: 
    typedef detail::Deleter<Object> deleter_type; 
    typedef boost::shared_ptr<deleter_type> deleter_pointer; 

    Pimpl(std::auto_ptr<Object> obj, deleter_pointer del); 
    ~Pimpl(); 
    Pimpl(const Pimpl&); 
    Pimpl& operator(const Pimpl&); 

private: 
    Object* mObject; 
    deleter_pointer mDeleter; 
}; 

Đó là một thành ngữ cổ điển trong C++, thêm thêm một mức gián tiếp :)

+0

Đây có phải là con trỏ thông minh để giữ cài đặt không? Không tăng scoped_ptr và shared_ptr đã hỗ trợ các loại không đầy đủ? – visitor

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