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

classe Test:perché protetto non protegge il membro in questa classe?

#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; 
} 

Sia msvc11 e g ++ compilare senza alcun errore.

Perché?

+0

Sembra ancora un altro motivo per non utilizzare i sindacati. –

+0

clang 3.2 restituisce 'errore: 'bBold' è un membro protetto di 'Base'' come previsto. gcc 4.7.2 non si lamenta (per 'protected' e anche per' private') – alfC

+0

msvc invia un avviso [C4201] (http://msdn.microsoft.com/en-us/library/c89bw853 (v = vs .71) .aspx) – spiritwolfform

risposta

8

Il seguente codice non è corretto per lo standard.

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

E 'GNU-extension

Tuttavia, clang dà l'errore, quando si tenta di ottenere l'accesso a bBold, quindi, è probabilmente MSVC/GCC bug (tutto dipende realizzazione di questa estensione, credo, perché se prova ad accedere al membro a - riceverai l'errore corretto).

Quindi, dal momento che è C-extension, in cui non abbiamo specificatori di accesso, sembra che i membri di questa struttura anonima vengano inseriti nella sezione public.

+1

Non sono sicuro che sia contro lo standard. Si noti che la 'struct' nidificata non è un' 'nested type'' ma un oggetto non statico nidificato di un tipo di struttura anonimo. – CygnusX1

+0

@ Le strutture anonime CygnusX1 senza nomi non sono consentite dallo standard, è l'estensione gnu come posso vedere. – ForEveR

+2

Quindi * che * è contro lo standard, ma non quello che citi. Non esiste una definizione di tipo annidata qui, c'è? – CygnusX1

0

Il privato/protetto protegge solo i campi definiti nella stessa classe della parola chiave. Se si potrebbe fare il seguente trucco:

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

è ancora possibile accedere Foo::PublicBar::x

struct X { ... } è oggigiorno in C++ sinonimo di class X { public: ... }. Anche i campi sindacali sono pubblici.

Nel tuo caso, è possibile nasconderlo nel seguente modo:

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

Ora x è privata e la definizione di unione interiore non "fuga" in pubblico.

+0

Non credo che la risposta alla domanda sia "profonda". Questo codice non ha lo stesso problema (con 'gcc' in particolare):' Base di classe { protetta: struct { bool bBold; bool bFakeBold; }; ... ' – alfC

2

Come già accennato, le strutture senza nome sono un'estensione non standard. Poiché questa è un'estensione non standard, è valida per diversi compilatori implementarlo in modo leggermente diverso. Tuttavia, per le unioni anonime, esiste la stessa domanda. esempio modificato:

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

Questo dovrebbe causare una fase di compilazione errore/avviso/o diagnostica, ma GCC felicemente lo accetta. Testato con 4.5.3 e 4.7.2 di Ideone. Sospetto che questo sia un bug in GCC e, se MSVC lo accetta, anche un bug in MSVC.

Problemi correlati