Почему защита не защищает участника в этом классе?
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++ компилируются без ошибок.
Почему?
Ответы
Ответ 1
Следующий код неверен по стандарту.
struct {
bool bBold : 1;
bool bFakeBold : 1;
};
GNU-расширение
Однако, clang дает ошибку, когда вы пытаетесь получить доступ к bBold
, поэтому, вероятно, это ошибка MSVC/GCC (все зависит от реализации этого расширения, я думаю, поскольку, если вы попытаетесь получить доступ к a
член - вы получите правильную ошибку).
Итак, поскольку он C-extension
, где у нас нет спецификаторов доступа, похоже, что члены этой анонимной структуры будут вставляться в раздел public
.
Ответ 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.
Ответ 3
Частные/защищенные защищают только поля, определенные в том же классе, что и ключевое слово. Если бы вы сделали следующий трюк:
class Foo {
private:
class Bar {
public:
int x;
}
public:
typedef Bar PublicBar;
}
Вы можете получить доступ к Foo::PublicBar::x
struct X { ... }
теперь в С++ синоним 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
является закрытым, и определение внутреннего объединения не "течет" публично.