Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > union и класы С++


Автор: __nazar__ 10.3.2008, 21:51
Здраствуйте.
У меня возникла вот такая интересная ситуация при компиляции програмы: проблема в том что если о обединение входит клас то при компиляции возникает ошибка.

Вот програма (написана на Visual C++): 

#pragma once

#include <complex>
#include "matrix.h"

typedef class std::complex<long double> LongComplex;

typedef enum EOperation {UNKNOWN,DEGREE,MUL,DIVD,AND,OR,XOR,NOT,DIV,MOD,PL US,MINUS} OPERATION;
typedef enum ESwitcher {EMPTY,NUMBER,MATRICA,ACT} SWITCHER;

typedef class CElement
{
public:
SWITCHER GetElementType() {return sw;};
LongComplex& GetNumber();
OPERATION& GetOperation();
MATRIX& GetMatrix();
void SetNumber(LongComplex num);
void SetOperation(OPERATION n);
void SetMatrix(MATRIX& m);
void Clear();
private:
union
{
LongComplex number;
OPERATION op;
MATRIX matr;
}element;
SWITCHER sw;
} ELEMENT,* PELEMENT;

А вот ошибка error C2620: member 'CElement::number' of union 'CElement::<unnamed-tag>' has user-defined constructor or non-trivial default constructor.

Но самое удивительное, то что MATRIX тоже класс но он ошибки не видайот потому что имеет конструктор и деструктор по умолчанию (то есть вобще их не имеет).

Что можете посоветовать. как решыть ету проблему (обединение нужно использовать обязательно)?

Автор: Daevaorn 10.3.2008, 22:02
Цитата(__nazar__ @  10.3.2008,  22:51 Найти цитируемый пост)
 имеет конструктор и деструктор по умолчанию (то есть вобще их не имеет).

Это и есть условие

Автор: __nazar__ 10.3.2008, 22:05
так что мне делать, не переписывать же стандартну библиотеку smile

Добавлено через 3 минуты и 39 секунд
В принципе я зделал так:

#pragma once

#include <complex>
#include "matrix.h"

typedef class std::complex<long double> LongComplex;

typedef enum EOperation {UNKNOWN,DEGREE,MUL,DIVD,AND,OR,XOR,NOT,DIV,MOD,PLUS,MINUS} OPERATION;
typedef enum ESwitcher {EMPTY,NUMBER,MATRICA,ACT} SWITCHER;

typedef class CElement
{
public:


    SWITCHER GetElementType() {return sw;};
    LongComplex&    GetNumber();
    OPERATION&        GetOperation();
    MATRIX&            GetMatrix();
    void            SetNumber(LongComplex num);
    void            SetOperation(OPERATION n);
    void            SetMatrix(MATRIX& m);
    void            Clear();
private:
/*    union
    {
        LongComplex number;
        OPERATION op;
        MATRIX matr;
    }element;*/
    char element[sizeof(LongComplex)];
    SWITCHER sw;
} ELEMENT,* PELEMENT;

потом просто преобразовую типы, просто интересно может есть какие-то другие способи?

Автор: korian 10.3.2008, 22:26
можно, например, использовать указатели в объединение, вместо самих объектов.

Автор: __nazar__ 10.3.2008, 23:10
тогда и що 4 байта на каждий указатель

Автор: bsa 11.3.2008, 00:25
__nazar__, в union будет выделено памяти только под элемент максимального размера. Т.е. если у тебя внутри union будет 3 указателя, то памяти будет выделено под объединения всего sizeof(void*).
Объекты в union не должны иметь пользовательских конструкторов (и конструируемых полей), так как это может привести к порче данных одного объекта конструктором другого.

Автор: Mayk 11.3.2008, 06:35
Цитата(__nazar__ @  11.3.2008,  02:05 Найти цитируемый пост)
потом просто преобразовую типы, просто интересно может есть какие-то другие способи?

Boost.variant. или boost.anytype. Лично мне первый больше нравится.

Цитата(__nazar__ @  11.3.2008,  03:10 Найти цитируемый пост)
тогда и що 4 байта на каждий указатель 

И чо?

Автор: Lazin 11.3.2008, 09:19
как вариант, вместо union-а можно использовать размещающее конструирование, забить буфер достаточной длины, и размещать там что угодно)), а вообще, конечно лучше boost::any, но any использует динамическую память...

Автор: Earnest 11.3.2008, 11:30
Не используй union. Это наследие C и с классами плохо смешивается. Даже если держать там только указатели, нужно писать поддержку нормального создания \ освобождения, иначе получится небезопасно.
А когда ты все это напишешь как следует, то получишь что-то вроде бустовских оболочек, только хуже. Так что согласна с Mayk: boost::variant.
 
Mayk, у any и variant просто разные области применения. Там где нужен именно any, variant ужасно неудобно использовать - и наоборот. Но у аффтора явно случай variant - строго заданный набор типов.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)