2013-06-25 74 views
12
class Base { 
    protected: 
     union { 
      struct { 
       bool bBold : 1; 
       bool bFakeBold : 1; 
      }; 
      int a; 
     }; 
    public: 
     bool isBold() { 
      return bBold; 
     } 
}; 

Test类:为什么保护不会保护这个班级的成员?

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

为什么?

+0

看起来还有一个不使用工会的理由。 –

+0

clang 3.2给出了'错误:'bBold'是预期的'Base'的受保护成员。 gcc 4.7.2不抱怨(对于'protected',甚至对'private') – alfC

+0

msvc给出警告[C4201](http://msdn.microsoft.com/en-us/library/c89bw853(v = vs .71).aspx) – spiritwolfform

回答

8

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

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

这是GNU-extension

然而,铛给人错误,当您尝试以访问bBold,因此,它可能是MSVC/GCC的bug(一切都取决于实现这一扩展的,我想,因为如果您尝试访问a成员 - 您将收到正确的错误)。

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

+1

我不确定它是否违反标准。请注意,嵌套'struct'不是''嵌套类型',而是一个匿名结构类型的嵌套非静态对象。 – CygnusX1

+0

@ CygnusX1没有名字的匿名结构是标准所不允许的,它是gnu-extension,我可以看到。 – ForEveR

+2

然后* *表示违反标准,但不是您引用的内容。这里没有嵌套类型定义,是吗? – CygnusX1

0

private/protected仅保护与关键字在同一类中定义的字段。如果一个人会做下面的技巧:

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

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

struct X { ... }在C++中的class X { public: ... }一个synonim nowdays。工会的领域也是公共的。

在你的情况,你可以通过以下方式将其隐藏:

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

现在x是私人和内部联盟的定义不“泄漏”到公众。

+0

我不认为这个问题的答案是“深”。这个代码不具有相同的问题(特别是'gcc'):''class base { protected: struct struct { bool bBold; bool bFakeBold; }; ...' – alfC

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中的一个错误。