不应该禁止访问私有类型吗?

Shouldn't access to private types be prohibited?

本文关键字:类型 禁止 访问 不应该      更新时间:2023-10-16

请考虑以下代码:

class A
{
struct B {};
std::vector<B> _vec;
public:
const std::vector<B>& get() const { return _vec; }
};

请注意,B在类A中是私有的。上面的代码可以编译,但是当从类A外部调用get()时,它不会:

const std::vector<A::B>& vec = get(); // does not compile

确实,A::Bprivate.但是,从C++11开始,您可以简单地执行以下操作:

const auto& vec = get();

这很完美。

出于与上述相同的原因,您无法执行以下操作:

A::B obj; 

但是,由于有一个public吸气剂,你可以从那个吸气器函数中推断出类型。在这种特殊情况下,可以执行以下操作:

using B = std::decay<decltype(C{}.get())>::type::value_type;
B obj;

问题

我不知道如何表述我的问题。对我来说似乎很奇怪,从 C++11 开始(而不是之前(,我们实际上可以实例化A::B成为后者private。更重要的是,我认为我们可以称之为const auto& get()很奇怪.对此有什么解释吗?不被允许这样做不是更好吗?我应该声明A::Bpublic吗?我觉得如果你需要一个像上面代码中的那个 getter 函数,那么private声明它是没有意义的。

对我来说,从

C++11 开始(而不是之前(,我们实际上可以将 A::B 实例化为后者是私有的,这对我来说似乎很奇怪。

您可以在 C++98/03 中通过模板参数推导很好地做到这一点:

template<typename T>
void temp_func(const T &t)
{
...
T u = t;
}
temp_func(a.get()); //Will use the private type.

您甚至可以在temp_func内部使用T

将类型设为私有从来都不能保证使该类型无法从外部访问。Private 始终是指名称的可访问性,而不是名称背后的构造。如果希望某个类型仅在作用域内使用,则该类型名不能是任何非专用接口的一部分。情况一直如此。

我应该公开A::B吗?

这取决于你。但是,如果公开公共用户界面,则声明用户可以使用该接口。为了让用户知道如何使用vector<A::B>,他们必须知道A::B的行为方式。所以他们必须使用它的定义。即使它是私人的。

因此,如果用户必须了解类型以及类型的行为方式......真的是"私人"吗?

当您标记私有内容时,并不意味着无法访问。它只是意味着无法从外部访问声明。

例如,这将起作用:

class A {
struct B {};
public:
using C = B;
};
auto main() -> int {
auto c = A::C{}; 
}

在这里我访问B,因为我使用了公共别名。

私人会员也是如此:

class A {
int i;
public:
auto the_i() -> int A::* {
return &A::i;
}
};
auto main() -> int {
auto a = A{};
auto member = a.the_i();
// Whoa! I access the member directly! Shouldn't this prohibited?
a.*member = 9;
}

答案是否定的。声明是私有的,但仍可以通过其他方式访问。

成员类型也是如此,在公共接口中公开它,用户将能够使用它。

如果您不希望用户使用私有类型,请不要在公共接口中公开它。