2013-06-25 72 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中的一個錯誤。