Đây là cách đơn giản hóa những gì tôi thấy khi tôi cố gắng sử dụng unique_ptr cho pimpl. Tôi đã chọn unique_ptr vì tôi thực sự muốn lớp sở hữu con trỏ - tôi muốn thời gian tồn tại của con trỏ pimpl và lớp đó giống nhau.Làm cách nào để sử dụng unique_ptr cho pimpl?
Dù sao, đây là tiêu đề:
#ifndef HELP
#define HELP 1
#include <memory>
class Help
{
public:
Help(int ii);
~Help() = default;
private:
class Impl;
std::unique_ptr<Impl> _M_impl;
};
#endif // HELP
Dưới đây là nguồn:
#include "Help.h"
class Help::Impl
{
public:
Impl(int ii)
: _M_i{ii}
{ }
private:
int _M_i;
};
Help::Help(int ii)
: _M_impl{new Help::Impl{ii}}
{ }
tôi có thể biên dịch chúng thành một thư viện tốt. Nhưng khi tôi cố gắng sử dụng nó trong một chương trình thử nghiệm tôi nhận được
[email protected]:~/ext_distribution$ ../bin/bin/g++ -std=c++0x -o test_help test_help.cpp Help.cpp
In file included from /home/ed/bin/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/../../../../include/c++/4.7.0/memory:86:0,
from Help.h:4,
from test_help.cpp:3:
/home/ed/bin/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h: In instantiation of 'void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = Help::Impl]':
/home/ed/bin/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:245:4: required from 'void std::unique_ptr<_Tp, _Dp>::reset(std::unique_ptr<_Tp, _Dp>::pointer) [with _Tp = Help::Impl; _Dp = std::default_delete<Help::Impl>; std::unique_ptr<_Tp, _Dp>::pointer = Help::Impl*]'
/home/ed/bin/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:169:32: required from 'std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = Help::Impl; _Dp = std::default_delete<Help::Impl>]'
Help.h:6:7: required from here
/home/ed/bin/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:63:14: error: invalid application of 'sizeof' to incomplete type 'Help::Impl'
Đây là một nổi tiếng safety feature. Tôi đã cố gắng làm theo.
Vấn đề của tôi là nếu tôi đặt Trợ giúp :: Khai báo Impl trong tiêu đề, nó có vẻ sẽ làm giảm bớt lợi thế của pimpl. Bố cục lớp hiển thị với người dùng. Định nghĩa bị ẩn nhưng tôi có thể làm điều đó với lớp Trợ giúp và các thành viên riêng tư. Ngoài ra, bao gồm cả tuyên bố của Impl mang đến các tiêu đề mới mà tôi muốn giữ riêng biệt.
Tôi đang thiếu gì? Những gì folks đặt trong một tuyên bố Impl và ở đâu? Tôi có làm trợ giúp dtor sai? Argh!
Xem thêm [GotW # 101: Tường lửa biên soạn, Phần 2] (http://herbsutter.com/gotw/_101/) và [câu hỏi liên quan này] (http://stackoverflow.com/q/8595471/636019). – ildjarn
Mặc dù đó là một câu hỏi cũ, nó có thể có liên quan để chỉ ra rằng, [như được giải thích trong cppreference] (http://en.cppreference.com/w/cpp/language/pimpl), một PImpl thực hiện với 'unique_ptr' nên được bọc trong một cái gì đó như ['propagate_const'] (http://en.cppreference.com/w/cpp/experimental/propagate_const) để có được sự chính xác hoàn chỉnh. – jdehesa
@jdehesa Cảm ơn bạn, tôi đã xem xét propagate_const như một giải pháp cho một số lúng túng của API. Tôi gần như tự hỏi nếu unique_ptr bị phá vỡ theo mặc định trong ý nghĩa này. Nó có vẻ như propagate_const nên được xây dựng trong hoặc ít nhất là mặc định. – emsr