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

我从g ++得到一个非常不寻常的错误,声称类型别名是私有的。 在缩短我的代码几个小时之后,我已经到了以下最小的测试用例:

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?

执行以下任何操作会阻止发生的错误:

  • Test转换为类,而不是模板类。
  • 删除任何函数中的任何语句。
  • 更改TheCatDog::Dog::bark(); CatDog::Dog::bark();
  • 删除CrazyHouse类并在Test合并其内容。
  • 删除CatDog类,将其内容合并到Test并将TheCatDog别名更改为指向Test

  • 标识符CatDog上的名称查找会查找被声明为private Test::CatDog 。 访问由CrazyHouse执行,它不是Testfriend 。 因此,这是对受保护成员的非法访问。

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

    C ++ 98:

    嵌套类的成员对封闭类的成员没有特殊的访问权限,也没有对授予封闭类的友谊的类或函数的特殊访问权限; 应遵守通常的访问规则(第11条)。

    C ++ 11:

    嵌套类是成员,因此具有与其他成员相同的访问权限。

    (会员有权访问封闭班的private会员。)

    但是,即使在4.9版本的最新版本中,这一变化似乎也未在GCC中实施。 所以,为了安全起见,添加friend声明无妨。 这必须遵循成员的定义:

    friend struct CrazyHouse;
    

    请注意,这不会完成与C ++ 11更改完全相同的事情,因为friend出货不是传递式的,而嵌套成员资格授予的访问权限是。


    取决于我们正在讨论的C ++版本,编译器的行为可能被认为是错误或正确的。 看起来,如果我们在谈论C ++ 11时,clang的行为是正确的,如果我们正在谈论C ++ 98,那么它是不正确的。

    stackoverflow项目C ++嵌套类访问应澄清。

    链接地址: http://www.djcxy.com/p/77717.html

    上一篇: C++: Strange "is private" error

    下一篇: Best Practice for Using a Dependency Injection / Service Locator Container?