Использование объединения внутри класса - PullRequest
12 голосов
/ 28 марта 2011

Я видел следующий код:

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

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

Ответы [ 4 ]

19 голосов
/ 28 марта 2011

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

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

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

        p->next = NULL;
    }
};

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

12 голосов
/ 28 марта 2011

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

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

0 голосов
/ 28 марта 2011

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

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

0 голосов
/ 28 марта 2011

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

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

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

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

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

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

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