2011-03-27 5 views
11

Я видел некоторый код следующим образом:Использование объединения внутри класса

class A 
{ 
private: 
    union { 
     B *rep; 
     A *next; 
    }; // no variables of this anonymous defined! 

    void func() 
    { 
     A *p = new A; 

     p->next = NULL; // why p has a member variable of 'next'? 
    } 
}; 

Я составил приведенный выше код с VS2010 без каких-либо ошибок. Занесен вопрос в личность:

Почему p имеет переменную члена 'next'?

union { 
     B *rep; 
     A *next; 
    }; 

Насколько я знаю, это анонимный союз, даже не определяющий переменную. Как мы можем получить доступ к переменным-членам внутри этого объединения?

ответ

16

Потому что это довольно много, что анонимный союз делает, он определяет нуль-или-больше переменных в пространстве имен объемлющего (что в объявлении класса делает их имена полей), которые занимают перекрывающуюся память. Следовательно, при использовании его так же, как если бы вы объявили

class A 
{ 
private: 
    B *rep; 
    A *next; 

    void func() 
    { 
     A *p = new A; 

     p->next = NULL; 
    } 
}; 

... за исключением повторения и рядом занимая перекрывающее пространство (или, учитывая, что два указателя будет иметь тот же размер, то же пространство), и, следовательно, все опасности и выгоды, которые приходят с названным союзом.

+0

«Потому что это в значительной степени то, что делает анонимный союз» - что хорошего. Если я дам переменную в конце определения объединения, то код будет недействительным больше - спасибо – q0987

0

Я не уверен, что понимаю ваш вопрос.

A имеет член p, потому что вы объявили его в A внутри анонимного объединения вместе с rep.

Вы объявили переменную! Просто «rep» и «next» используют одну и ту же память.

Вы можете получить к нему доступ так же, как и вы.

анонимные союзы (как и структуры) помещают их члены в то же пространство имен, что и указанное пространство имен.

Это полезно, например:

union W00t { 
    struct { 
     uint32_t a,b; 
    }; 
    struct { 
     uint64_t c; 
    }; 
} 
+0

Ваш ответ не связан с моим вопросом. Я спросил: «Почему переменная p может получить доступ к следующей переменной?» – q0987

+0

mh Я не сожалею ^^. Вы объявили переменную. Просто у него нет имени, используя, таким образом, указанное пространство имен? На самом деле я не знаю, что сказать. –

+0

следующий действительно часть A. Как rep. Оба являются членами ... Но rep и next используют одну и ту же 64-разрядную память. ((И p - это A *, поэтому указатель на экземпляр A, таким образом, имеет все члены A.)) –

0

Я удивлен, что есть современный компилятор, который до сих пор позволяет эту конструкцию. Это один из первых дней C, около 1975 года. В те дни структура и члены профсоюза фактически не были привязаны к определенной структуре, но содержали в качестве атрибутов смещение от базового адреса и типа данных.

Конечным результатом было то, что использование структуры или объединения правильно приводит к правильному коду с выражениями, оцененными как ожидалось. Единственное различие заключается в том, что неправильное использование элемента структуры с указателем, не связанным с типом, не будет помечено как ошибка. Я не думаю, что была какая-то особая причина для того, чтобы не применять привязку-ассоциированный-K & R, что будущие компиляторы надеюсь, что будет проверять такие виды использования - возможно, просто для сохранения табличного пространства символов в 16-битной стране.

+0

новейшим gcc нравится. Имо имеет смысл, если вы используете union {struct {}} ... не имея другой области/имени между –

+1

Конечно, компиляторы разрешают эту конструкцию, это часть стандарта (и все еще есть в C++ 0x). Я опубликую соответствующий раздел. –

+0

Он также по-прежнему имеет практическое применение вне злоупотребления, чтобы сэкономить место. Множество «плохих» вещей, которые можно делать в C и C++, необходимы в некоторых случаях при работе с наложенными физическими макетами, поэтому, хотя выше было бы плохо, если бы сбережение пространства было единственным намерением (хотя даже это было бы прощено на небольшом устройство с несколькими КБ для воспроизведения), в некоторых случаях это может быть абсолютно необходимо. –

11

Вот цитата из стандарта, который управляет этим поведением: раздел [class.union] (формулировка из C++ 0x проекта n3242)

союзной формы union {член-спецификации} ; называется анонимным союз; он определяет неназванный объект неназванного типа. Спецификация анонимного соединения определяет только нестатические элементы данных. [Примечание. Вложенные типы и функции не могут быть объявлены в анонимном объединении.- конец примечания] Имена членов анонимного союза должны отличаться от имен любого другого объекта в области, в которой объявлен анонимный союз. Для целей поиска имени, после анонимного профсоюзного определения члены анонимного союза считаются определенными в области, в которой объявлен анонимный союз.

+0

вы всегда можете предоставить ОТВЕТ! - спасибо – q0987

+2

@ q0987: Я думаю, что [Jon] (http://stackoverflow.com/questions/5453170/usage-of-union-inside-a-class/5453262#5453262) заработал галочку. Я не сделал ничего, кроме ссылки на стандарт для ссылки, чтобы доказать, что его гораздо более читаемый ответ правильный. Я бы использовал комментарий, но я давно понял, что цитаты из стандарта обычно не вписываются в комментарий и не хорошо форматируются. –

+0

да, я внес изменения, как вам нужно. -- спасибо – q0987

Смежные вопросы