简体   繁体   中英

Problems with nested struct constructor and Union

I have a struct nested winin a class and a union of that struct. If I have a struct constructor that takes arguments, then the union won't compile.

I also want to create an instance of the struct using an argument. That line also fails.

class test
{
public:
test(void);
~test(void);

struct dtType {
    // inline constructors with initialisation lists
    dtType() : mins(0), hrs(0),day(0),mnth(0),year(0),DPOffset(0),DTType(0) {}
    dtType(byte z) : mins(z), hrs(z),day(z),mnth(z),year(z),DPOffset(0),DTType(0) {}
    dtType(byte n,byte h, byte d, byte m, byte y, byte o, byte t) : mins(n), hrs(h),day(d),mnth(m),year(y),DPOffset(o),DTType(t) {}

    // overloaded operator functions
    bool operator< (dtType date){return true;};
    bool operator<= (dtType date){return true;};
    bool operator> (dtType date){return true;};
    bool operator>= (dtType date){return true;};
    bool operator== (dtType date){return true;};

    // data members
    unsigned mins: 3;
    unsigned hrs: 5; // 8 bits
    unsigned day: 5; 
    unsigned mnth: 4;
    unsigned year: 7; // 16 bits
    unsigned DPOffset: 6; 
    unsigned DTType  : 2;
};

// if I comment out the union it compiles, otherwise I get:
// error C2620: member 'test::dtUnion::dt' of union 'test::dtUnion' has user-defined  constructor or non-trivial default constructor

union dtUnion { 
    dtType dt;
    unsigned long dtLong; // 32 bits
} dtU;

// if I call dtType judgement_day(); it compiles. Otherwise I get:
dtType judgement_day(1); // error C2059: syntax error : 'constant'

};

Following the answers below I have now tried the following, but I get error C2438: judgement_day,dateMask,timeMask : cannot initialize static class data via constructor

class test
{
public:
    test(): judgement_day(1),dateMask(1,1,1,1,1,0,0),timeMask(1,1,0,0,0,0,0){}
~test();
public:
struct dtType {
    // inline constructors with initialisation lists
    dtType() : mins(0), hrs(0),day(0),mnth(0),year(0),DPOffset(0),DTType(0) {}
    dtType(byte z) : mins(z), hrs(z),day(z),mnth(z),year(z),DPOffset(0),DTType(0) {}
    dtType(byte n,byte h, byte d, byte m, byte y, byte o, byte t) : mins(n), hrs(h),day(d),mnth(m),year(y),DPOffset(o),DTType(t) {}
    // overloaded operator functions
    bool operator< (dtType date){return true;};
    bool operator<= (dtType date){return true;};
    bool operator> (dtType date){return true;};
    bool operator>= (dtType date){return true;};
    bool operator== (dtType date){return true;};
    // data members
    unsigned mins: 3;
    unsigned hrs: 5; // 8 bits
    unsigned day: 5; 
    unsigned mnth: 4;
    unsigned year: 7; // 16 bits
    unsigned DPOffset: 6; 
    unsigned DTType  : 2;
};
const static dtType judgement_day;
const static dtType dateMask;
const static dtType timeMask;
};

Having union members with explicit constructors is disallowed by the standard, it has nothing to do with the union being a member or a nested type.

The following would also fail to compile:

struct X
{
    X() {};
};
union Y
{
    X k;
};

Others have answered the question about the union; it can't contain members with non-trivial default constructors. To answer the second question, about member initialisation:

You can't initialise non-static members in the class definition; they have to be initialised in the constructor's initialiser list:

class test {
    // stuff
    dtType judgement_day;
};

test::test() : judgement_day(1) {}

The reason that dtType judgement_day(); compiles is that it's declaring a function, not a variable.

UPDATE: since you actually want these members to be static, they are instead initialised in a source file, similarly to global variables:

// in the header
class test {
    // stuff
    const static dtType judgement_day;
};

// in exactly one source file
const test::dtType dtType::judgement_day(1);

A union can not contain class instances. Consider a union containing two objects, when creating that union which constructor should be called? The compiler can't call both constructors as that may cause one object to contain faulty values.

For as long as the union contains a dtType member, then dtType cannot have constructors.

However you can change your contructors to be void Set() functions instead, to be called implicitly after a construction.

For example:

int main()
{
    test::dtType judgement_day;
    judgement_day.Set(1);

    test::dtUnion x;
    x.dt.Set(1);

    assert(judgement_day == x.dt);
    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM