大多数 Pimpl 示例如下:
更新:两种情况均失败,即使用和不使用命名空间。请参阅https://stackoverflow.com/a/57103016/2712726中R Sahu的回答。 Impl类必须使用类名Simpl
// Simple.h
#include <memory>
class Simple {
struct Impl; // WORKS!
std::unique_ptr<Impl> impl_;
public:
Simple();
~Simple();
int get() const;
};
但是,在使用命名空间的现实世界中,这似乎失败了。 如果存在名称空间,则必须将前向声明移到类声明之前。谁能解释为什么?
// Simple.h but now with name spaces
namespace weired::example {
struct Impl; // OK! forwad declaration must go here
class Simple {
//struct Impl; // ERROR! incomplete type in ctor definition
std::unique_ptr<Impl> impl_;
public:
Simple();
~Simple();
int get() const;
};
}
我已经使用gcc9
和clang8
以及-std=c++11
到c++2a
对此进行了测试。
为了完整起见,这里有Simple.cpp和main.cpp文件,因此您可以自己运行示例:
// Simple.cpp
#include "Simple.h"
namespace weired::example {
struct Impl {int a,b;};
Simple::Simple() : impl_(new Impl{3,4}) {}
Simple::~Simple() = default;
int Simple::get() const
{
return impl_->a;
}
}
和
// main.cpp
#include "Simple.h"
#include <iostream>
int main () {
auto nonsense = weired::example::Simple{};
std::cout << nonsense.get() << '\n';
}
答案 0 :(得分:2)
无论Impl
是在命名空间中定义还是在全局中定义,您都可以在类内部和类外部转发声明Simple
。
在两种情况下,Impl
的实现几乎相同。
namespace
Impl
是对等类).h文件
struct Impl;
class Simple { ... };
.cpp文件
// Define Impl
struct Impl { ... };
// Define Simple
Impl
是嵌套类).h文件
class Simple
{
struct Impl;
...
};
.cpp文件
// Define Impl
struct Simple::Impl { ... }; // Need the Simple:: scope here.
// Define Simple
namespace
Impl
是对等类).h文件
namespace weired::example {
struct Impl;
class Simple { ... };
}
.cpp文件
namespace weired::example {
// Define Impl
struct Impl { ... };
// Define Simple
}
Impl
是嵌套类).h文件
namespace weired::example {
class Simple
{
struct Impl;
...
};
}
.cpp文件
namespace weired::example {
// Define Impl
struct Simple::Impl { ... }; // Need the Simple:: scope here.
// Define Simple
}