How do I use the constructors in a named union? And how can I change the values in the same union instance later? c++/c++11

StackOverflow https://stackoverflow.com/questions/21808695

  •  12-10-2022
  •  | 
  •  

문제

I have a bit of code somewhat like this:

class Token{
   public:

    union tester{
        double literal;
        string name;

        tester(double op) : literal(op) {};
        tester(string val) : name(val) {};
        tester(): tester(0.0) {};
    };

    void setUp(){
      //the literal and name members of tester should be initialized here
    };
    /*other functions are below, two of which require that the values of literal 
      and name can be changed*/
};

I need to initialize both the literal and name members, but I'm not sure how. I have tried making a variable of type tester and doing this: tester test(45.0);, but then I can only set one of the member variables, and simply using tester(45.0); doesn't work either I tried this: Token thing; thing.name = "Elly", that didn't work. My class doesn't use constructors either. So, my questions are, how can I set and then later change the values of the member variables in tester in Token?

I am using the C++11 compiler.

(I apologize in advance if this question has been answered already or is too silly, I have been looking around, but I really don't understand how I can get this to work. I'm missing something, but I'm not quite sure what.)

도움이 되었습니까?

해결책

In a nutshell: don't do it.

Unions are really best used when representing data that has the same binary representation, e.g.:

union v4f {
    float f[4];
    struct {
      float x;
      float y;
      float z;
      float t;
    };
};

v4f v;
v.f[1] = 2.f;
v.t = 0.f;

Assuming you do actually want to use a union here, and not a struct, i.e. a token contains a name OR a literal, but never both at the same time, and you really need to save on the extra storage that a using struct would cost:
Before C++11, you couldn't have a union member with a non=trivial destructor, such as your tester.name string field. See this question for more details.

Now, this is possible, although I would recommend not doing it unless you really know what's going on. To do that, you need to define your union's destructor, because it the compiler cannot decide which, if any of the non-trivial union members to delete. I think you are better off avoiding this, because this is not an easy question to answer, without any additional information:

~tester() {
// delete name member or not ?
// very hard to decide without additional data
}

As for how to access your union member, since your union is not anonymous, it can't be accessed anonymously, so you need to actually create a member of your class with this union type, and refer to that class member.

class Token {
public:
    union tester {
        double literal;
        string name;

        tester(double op) : literal(op) {};
        tester(string val) : name(val) {};
        tester(): tester(0.0) {};
        ~tester() {}
    };
    tester data;
    ...
};

...
Token t;
t.data.name = "Elly";

다른 팁

Another use case of a union is to allocate 'enough' memory for all possible objects which must be stored, but only one at a time.

Example: Having a state machine which represents each state as a instance of a class. The state machine it self contains a union which is set up of all classes. Entering a state will simple be done by new at operator at the address of the union while leaving a state will be done by manually call of the destructor.

And there is also an often seen use case: casting via union. I think that is a very terrible anti pattern :-)

Coming back to the question: Initializing two members at the same! time is never possible inside a union. The second init will overwrite the data of the first initialized object. Maybe you want a struct or you have to think again for your design.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top