访问私有嵌套类

Sam*_*Lou 17 c++ language-lawyer c++11

我做了这个简单的课程,仍然在玩我的想法:

class A {
private:
    class B {};

public:
    B getB() {
        return B();
    };
};
Run Code Online (Sandbox Code Playgroud)

从C++ 03开始,这个类编译得很好,但是没有很好的方法可以将结果分配给getB()左值,在这个意义上:

A::B b = A().getB();
Run Code Online (Sandbox Code Playgroud)

不编译.

我通过使用中间模板得到它,以这种方式:

template <typename T>
struct HideType {
    typedef T type;
};

HideType<A::B>::type b = A().getB();
Run Code Online (Sandbox Code Playgroud)

但这看起来很糟糕,因为这个简单的任务是得到一个A :: B左值变量.

从C++ 11开始就不再这样了,或者至少它不适用于gcc.此代码仍无效:

A::B b = A().getB();
Run Code Online (Sandbox Code Playgroud)

但这有效的:

auto b = A().getB();
Run Code Online (Sandbox Code Playgroud)

标准方面是否存在漏洞?

Vic*_*nko 10

从标准,第11条(会员访问控制):

班级成员可以是
私人的; 也就是说,它的名称只能由声明它的类的成员和朋友使用.
- 受保护; 也就是说,它的名称只能由声明它的类的成员和朋友,从该类派生的类以及他们的朋友使用(见11.4).
- 上市; 也就是说,它的名称可以在没有访问限制的任何地方使用.

因此,访问控制应用于名称.

auto b = A().getB();
Run Code Online (Sandbox Code Playgroud)

根据标准,你不使用私人名称,因此它是合法的


Anw*_*sha 1

A::B b = A().getB()之所以不起作用的事实是因为B是 的私有类成员A。如果您将其公开,那么您的代码将被编译。它可以工作auto,因为auto只需检查分配给它的对象的类型,而不需要调用对象的构造函数(就像declval)。因此它分配了class 中presentb的返回类型。您也可以通过以下方式更改代码:getBA

decltype( declval<A>().getB() ) b = A().getB();
Run Code Online (Sandbox Code Playgroud)

(如果declval对您来说是新的,那么我必须告诉您,它将返回类(此处)的函数(此处getB其返回类型是B)的返回类型的右值A,而不调用该类的构造函数!(但这应该是与decltypeand sizeofonly 等函数一起使用。)因此它可以防止创建类对象然后使用其函数的开销。)

现在根据我的说法,我不认为这是标准中的漏洞,而是我觉得漏洞已经被删除了!从您自己的代码中可以明显看出,请参阅该函数getB。实例化一个对象是多么困难,B因为它是在 private 中定义的!在这种情况下,合作B变得很困难。B这背后的想法是,类中的类型名称(即)A无法访问,但该类型仍然可用,这就是为什么您可以获得 的对象Bauto如果你理解这个模板代码,你就可以理解它的用法:-

#include <iostream>
#include <type_traits>  // for std::is_same
using namespace std;
class A
{
    class B
    {};
    public:
    B getB()
    {
        return B();
    }
};
template<typename T>
void check (T b)
{
    cout<<boolalpha;
    is_same<decltype( declval<A>().getB() ), T> x;  // checks if T & B are of same type
    cout<<x.value<<'\n';
}
int main()
{
    A obj;
    check (obj.getB());
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出 :-

true
Run Code Online (Sandbox Code Playgroud)

由于template可以识别B,因此auto也可以识别B