C++ Pimpl

一般写法:

Test.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Test
{
public:
Test(int a, int b);
~Test();

Test(const Test& other);
Test(Test&& other);

Test& operator=(const Test& other);
Test& operator=(Test&& other);

int GetResult();

private:
struct Impl;
std::unique_ptr<Impl> _impl;
};

Test.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
struct Test::Impl
{
// Test's private fields and member functions here

int calcResult()
{
return a * b + a + b;
}

int a{ 0 };
int b{ 0 };
};

Test::Test(int a, int b)
: _impl(new Impl())
{
_impl->a = a;
_impl->b = b;
}

Test::~Test()
{
// Note: because std::unique_ptr will be destruct automatically
//_impl = nullptr;
}

Test::Test(const Test& other)
: _impl(new Impl(*other._impl))
{
}

Test::Test(Test&& other)
: _impl(std::move(other._impl))
{
}

Test& Test::operator=(const Test& other)
{
// we still need this to avoid memory allocation
if (this == &other) {
return *this;
}

_impl = std::unique_ptr<Impl>(new Impl(*other._impl));

return *this;
}

Test& Test::operator=(Test&& other)
{
// Note: because std::unique_ptr has checked for this condition
//if (this == &other) {
// return *this;
//}

_impl = std::move(other._impl);

return *this;
}

int Test::GetResult()
{
return _impl->calcResult();
}

没有其它指针数据,构造和赋值可简化为:

1
2
3
4
Test::Test(Test&&) = default;
Test::Test(const Test&) = delete; // 需要写在头文件里
Test& Test::operator=(Test&&) = default;
Test& Test::operator=(const Test&) = delete; // 需要写在头文件里

也就是:

Test

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// Test.hpp
class Test
{
public:
Test();
~Test();

Test(Test&& other);
Test(const Test& other) = delete;

Test& operator=(Test&& other);
Test& operator=(const Test& other) = delete;

private:
struct Impl;
std::unique_ptr<Impl> _impl;
}

// Test.cpp
struct Test::Impl
{
}

Test::Test()
: _impl(std::make_unique<Impl>())
{
}

Test::~Test() = default;

Test::Test(Test&& other) = default;
Test& Test::operator=(Test&& other) = default;