我有以下课程:
struct pool : public std::enable_shared_from_this<pool> {
private:
struct manager {
explicit manager(const std::weak_ptr<pool> &pool) : m_pool{pool} {
}
explicit manager() = default;
auto operator()(connection *conn) -> void;
private:
std::weak_ptr<pool> m_pool;
};
public:
pool(const pool &) = delete;
auto operator=(const pool &) -> pool & = delete;
auto borrow() noexcept -> std::unique_ptr<connection, manager>;
}
其中connection
与pool
具有相同的可见性。
在测试中,我可以将borrow()
与auto一起使用:
auto p = std::make_shared<pool>();
auto conn = p->borrow();
但是我无法声明与返回类型borrow()
相同类型的变量:
std::unique_ptr<connection, manager> conn;
clang返回错误:
error: 'manager' is a private member of 'dbc::detail::pool'
这两个不是可互换的吗?
答案 0 :(得分:1)
如果使用decltype
,您可以声明所需的变量:
decltype(p->borrow()) conn = p->borrow();
访问控制适用于名称,而不适用于定义或数据。
即使类型的名称是私有的,只要您不命名,就可以使用它。
下面是一个没有auto
的示例:
class A
{
struct B { int x; } m_b;
public:
B f() { return m_b; }
};
int main()
{
A a;
std::cout << a.f().x; // Compiles, since 'A::B::x' is public.
decltype(a.f()) b1; // Compiles, since the name 'B' is not used.
A::B b; // Doesn't compile, since the name is private.
}
答案 1 :(得分:0)
这两个不是可互换的吗?
不,不一定。私有结构将被视为实现细节,因此可以在类的将来版本中将其删除或重命名。因此,不允许任何人(在类外部)拼写私有结构的名称。
如果类的成员函数返回该私有类型的对象,则需要一种使用这些对象的方法。这样做的一种可能是关键字auto
。 (替代方法是decltype
和函数模板。后者在C ++ 11之前存在。)请注意,如果您决定重命名私有结构,则auto
关键字也将起作用。