C:奇怪的“是私人”错误

前端之家收集整理的这篇文章主要介绍了C:奇怪的“是私人”错误前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我一直在得到一个非常不寻常的错误,声称类型别名是私有的.经过几个小时的减少我的代码,我得到了以下最小的测试用例:
template <typename Dummy>
class Test {
    struct CatDog {
        static void meow ()
        {
            CrazyHouse::TheCatDog::meow();
        }

        struct Dog {
            static void bark ();
        };
    };

    struct CrazyHouse {
        using TheCatDog = CatDog;

        static void startMadness ()
        {
            TheCatDog::meow();
            TheCatDog::Dog::bark();
        }
    };

public:
    static void init ()
    {
        CrazyHouse::startMadness();
    }
};

int main ()
{
    Test<void> t;
    t.init();
}

g 4.8.2的错误是:

test.cpp: In instantiation of 'static void Test<Dummy>::CatDog::meow() [with Dummy = void]':
test.cpp:19:29:   required from 'static void Test<Dummy>::CrazyHouse::startMadness() [with Dummy = void]'
test.cpp:27:34:   required from 'static void Test<Dummy>::init() [with Dummy = void]'
test.cpp:34:12:   required from here
test.cpp:15:33: error: 'using TheCatDog = struct Test<void>::CatDog' is private
         using TheCatDog = CatDog;
                                 ^
test.cpp:6:41: error: within this context
             CrazyHouse::TheCatDog::meow();
                                         ^

Clang 3.4接受相同的代码.这里发生了什么,这是一个g bug吗?

执行以下任何操作可以阻止发生错误

>将测试转换为类,而不是模板类.
>删除任何功能中的任何语句.
>改变TheCatDog :: Dog :: bark(); to CatDog :: Dog :: bark();.
>删除CrazyHouse类并在Test中合并其内容.
>删除CatDog类,将其内容合并到Test中,并将TheCatDog别名更改为指向Test.

解决方法

标识符上的名称查找CatDog查找被声明为私有的Test :: CatDog.访问是从CrazyHouse执行的,CrazyHouse不是Test的朋友.因此,它是对受保护成员的非法访问.

正如@ sj0h所指出的,在C 11中,您的示例变得有效,因为它们决定以与成员函数相同的方式扩展对嵌套类主体的访问.

C 98:

The members of a nested class have no special access to members of an enclosing class,nor to classes or functions that have granted friendship to an enclosing class; the usual access rules (clause 11) shall be obeyed.

C 11:

A nested class is a member and as such has the same access rights as any other member.

(会员有权访问附上课程的私人会员.)

但是,即使在4.9版本的最新版本中,此更改似乎也未在GCC中实现.所以,为了安全起见,添加朋友声明不会有害.这必须在成员的定义之后:

friend struct CrazyHouse;

请注意,这与C 11更改完全不同,因为友谊不是传递的,而嵌套成员资格授予的访问权限是.

猜你在找的C&C++相关文章