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

klasa Test:dlaczego ochrona nie chroni członka w tej klasie?

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

Zarówno msvc11 i g ++ skompilować bez błędów.

Dlaczego?

+0

Wygląda na kolejny powód, aby nie używać związków. –

+0

clang 3.2 daje 'error: 'bBold' jest chronionym członkiem 'Base'' zgodnie z oczekiwaniami. gcc 4.7.2 nie narzeka (dla 'protected', a nawet dla' private') – alfC

+0

msvc daje ostrzeżenie [C4201] (http://msdn.microsoft.com/en-us/library/c89bw853 (v = vs .71) .aspx) – spiritwolfform

Odpowiedz

8

Następujący kod jest nieprawidłowy według standardu.

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

To GNU-extension

Jednak dzyń daje błąd podczas próby uzyskania dostępu do bBold, więc to chyba MSVC/bug GCC (wszystko zależy od realizacji tego rozszerzenia, myślę, ponieważ jeśli próbujesz uzyskać dostęp do członka a - otrzymasz poprawny błąd).

Tak więc, ponieważ jest to C-extension, gdzie nie mamy żadnych specyfikatorów dostępu - wygląda na to, że członkowie tej anonimowej struktury zostaną wprowadzeni w sekcji public.

+1

Nie jestem pewien, czy jest to niezgodne ze standardem. Zauważ, że zagnieżdżona 'struct' nie jest typem zagnieżdżonym, ale zagnieżdżonym niestatycznym obiektem anonimowego typu struct. – CygnusX1

+0

@ Anonimowe konstrukcje CygnusX1 bez nazw nie są dozwolone przez standard, jest to rozszerzenie gnu, jak widzę. – ForEveR

+2

Następnie * to * jest niezgodne ze standardem, ale nie tym, co cytujesz. Tu nie ma definicji typu zagnieżdżonego, prawda? – CygnusX1

0

Prywatne/chronione chronią tylko te pola, które są zdefiniowane w tej samej klasie co słowo kluczowe. Gdyby ktoś zrobić następującą sztuczkę:

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

Nadal można uzyskać dostęp Foo::PublicBar::x

struct X { ... } jest nowdays w C++ jest synonim z class X { public: ... }. Pola związku są również publiczne.

W twoim przypadku, można ukryć je w następujący sposób:

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

Teraz x jest prywatny i definicja wewnętrznej Unia nie „przeciek” do publiczności.

+0

Nie sądzę, że odpowiedź na to pytanie jest "głęboka". Ten kod nie ma tego samego problemu (w szczególności "gcc"): 'klasa Base { chroniona: struct { bool bBold; bool bFakeBold; }; ... ' – alfC

2

Jak już wspomniano, nienazwane struktury są niestandardowym rozszerzeniem. Ponieważ jest to niestandardowe rozszerzenie, ważne jest, aby różne kompilatory implementowały je w subtelny sposób inaczej. Jednak w przypadku anonimowych związków istnieje to samo pytanie. Zmodyfikowany przykład:

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

Powinno to spowodować kompilacji błąd/ostrzeżenie/inne diagnostycznym, ale GCC radośnie akceptuje. Testowane w wersji 4.5.3 i Ideone w wersji 4.7.2. Podejrzewam, że jest to błąd w GCC i jeśli MSVC również to zaakceptuje, to również błąd w MSVC.

Powiązane problemy