为什么受保护不保护这个班级的成员?

时间:2013-06-25 06:55:11

标签: c++

class Base {
    protected:
        union {
            struct {
                bool bBold : 1;
                bool bFakeBold : 1;
            };
            int a;
        };
    public:
        bool isBold() {
            return bBold;
        }
};

测试类:

#include <assert.h>
#include <stdio.h>

int main()
{
    Base d;
    d.bBold = false;
    assert(d.isBold() == false);
    d.bBold = true;
    assert(d.isBold() == true);
    printf("good");
    return 0;
}

msvc11和g ++都编译没有任何错误。

为什么?

3 个答案:

答案 0 :(得分:8)

以下代码标准不正确。

        struct {
            bool bBold : 1;
            bool bFakeBold : 1;
        };

这是GNU-extension

然而,当你试图访问bBold时,clang会出错,因此,它可能是MSVC / GCC错误(我认为,所有这些都取决于此扩展的实现,因为如果你试图访问{ {1}}成员 - 您将收到正确的错误。)

所以,因为它是a,我们没有访问说明符 - 看起来这个匿名结构的成员将被注入C-extension部分。

答案 1 :(得分:2)

如上所述,未命名的结构是非标准的扩展。因为这是一个非标准的扩展,所以不同的编译器有效地以不同的方式实现这一点。但是,对于匿名工会,存在同样的问题。修改过的例子:

class C {
    union {
        union {
            int i;
        };
    };
};
int main() {
    C c;
    c.i = 0;
    return c.i;
}

这应该导致编译时错误/警告/其他诊断,但GCC很乐意接受它。测试4.5.3和Ideone的4.7.2。我怀疑这是GCC中的一个错误,如果MSVC也接受了这个,也是MSVC中的一个错误。

答案 2 :(得分:0)

private / protected仅保护与关键字在同一类中定义的字段。如果有人会做以下诀窍:

class Foo {
    private:
    class Bar {
        public:
        int x;
    }
    public:
    typedef Bar PublicBar;
}

您仍然可以访问Foo::PublicBar::x

struct X { ... }现在是C ++中class X { public: ... }的同义词。工会领域也是公开的。

在您的情况下,您可以通过以下方式隐藏它:

class Base {
protected:
    union X {
        struct {
            bool bBold : 1;
            bool bFakeBold : 1;
        };
        int a;
    };
    X x;
public:
    bool isBold() {
        return x.bBold;
    }
};

现在x是私有的,内部联合的定义不会“泄漏”到公众中。