12
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++ 都编译没有任何错误。

为什么?

4

3 回答 3

8

以下代码按标准是不正确的。

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

这是GNU 扩展

但是,当您尝试访问时,clang 会出错,bBold因此,这可能是 MSVC/GCC 错误(我认为,这一切都取决于此扩展的实现,因为如果您尝试访问a成员 - 您将收到正确的错误)。

因此,由于它是C-extension,我们没有访问说明符 - 看起来这个匿名结构的成员将被注入到public部分中。

于 2013-06-25T07:03:56.043 回答
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 中的一个错误。

于 2013-06-25T07:35:18.937 回答
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是私有的,内部联合的定义不会“泄露”到公众中。

于 2013-06-25T07:03:28.690 回答