creating empty constructor for struct with anonymous union - c++

Trying to create empty constructor for a struct that has union as a member variable. Union also has a struct and an additional variable as member variables.
Took few approaches, but non were successful. How can I create an empty constructor for nested anonymous structures? How can I call the member variables afterwards?
typedef struct test_struct
{
int a;
union {
int b;
struct {
int c;
};
};
} test_struct;
Below won't compile
test_struct() : a(10), b(20), c(30) {
}
Below sets both b and c as 30
test_struct() : a(10), b(20) {
c = 30;
}
Here is the print function
int main(void)
{
test_struct *ts = new test_struct();
printf("%i\n%i\n%i\n", ts->a, ts->b, ts->c);
return 0;
}
I trying to create an empty constructor that will print 10 20 30 with my printf().
EDIT: I received comments on how I cannot initialize union in this way. However, the header file I received (which I cannot change at all) has structs defined in such nested structure. I do not know how the initialization goes in the back, but my code has to print out values for all the member variables. (a, b, and c for the below example code). Any approaches/reading I can do to achieve this?

Apart from the erroneous way you use union, let's stick to the question about your nested struct. The answer is simple: you can't specify constructors for nested structs. So, even if you fix the code and use correctly your nested struct, you won't be able to declare a constructor or destructor for that anonymous class/struct because the constructor and destructor names need to match the class name.
In the example you posted, the anonymous class is local. It means that it has no linkage so mangled name is not even created.

Related

How to refer a struct member value within itself?

Say I have the following simple struct in C/C++:
struct Example {
int member_a;
int member_b;
}
Now, I have an object ex of it.
For the sake of redundancy and properly relating some members, I need to assign member_b using the value of member_a. Here, as I knew the name of this object, something like this worked for me:
struct Example ex = {
.member_a = 50,
.member_b = ex.member_a * 2 // Assigning member_b in terms of member_a.
}
The above assignment works as long as int member_a is kept above int member_b in the declaration of Example struct.
I have already tried using .member_b = member_a ... and .member_b = .member_a ..., both of which failed to identify the member_a in a struct object. .member_b = <same_object_name>.member_a only seems to work with the initial definition.
Note: This all has been tried on version C18
It was a way out in case of this single struct object, but what if I do not want to use object name or if in case I'm using anonymous (unnamed) struct object? Can something like pointers or some equivalent of this exists that is compatible with C for using the relation in an object (or better if possible in struct definition itself)? Even being able to call a value of member like .member_a within Example struct shall do.
Update: If C and C++ vary a lot, please focus on a C specific solution.
C/C++ are two completely different languages if they're used modernly where C++ can take advantage of classes and the this keyword. I would assume that you want to use structs in C++ for this exact question.
If you want to just have a direct relationship for example member b is twice member, then just set them equal in the original class so that it happens during compile time.
struct Example {
int member_a;
int member_b = 2 * member_a;
};
Otherwise you have to explicitly site which struct you are using when accessing ints within it. In this case a struct doesn't have any members that strictly pertain to it and the compiler doesn't know if there's going to be a value at member_a. If you wanted to use a class then you would just set it at anytime to itself, with a function or set statement.
class Bob {
public:
int member_a;
int member_b;
private:
int double_member_a(){
member_b = 2 * member_a;
return member_b
};
};
Bob bob;
bob.member_a = 1;
bob.member_b = bob.member_a; // or bob.doubleA();
Regardless of the method you would still be changing a struct or classes values depending on that exact instance of the object so you would always have to state which one, though if you were going through any x struct of class you would just put them into a vector and do a range based for loop and access one at anytime.

assigning constant value to struct members to be used in 1 class

So far I've read about structs, with and without pointers. My question is about a struct in combination with a class and main. What I learn from K&R and c++ sites is that a struct can't contain values. The values I want to assign to the members will be constants. In several posts I read that I should put the struct inside the class and even inside private. The setup I use was:
class C
{
struct something {const float m = 3} s;` //actually 12 members. Compiler doesn't accept values: "ISO C++ forbids initialization of member"
function foo(struct something s){ float m = s.m; <..do something..>}` //struct s actually used in several functions
};
int main(){C c;}
Then I created 2 structs, and letting the 2nd assign values to the members of the first, which I find ugly. But why did that get accepted by gcc? So how can I assign the values only once in a proper way since assigning values has to be done inside a function. BTW, I'm using Ubuntu gcc-4.6.1.
Thank you for an answer.
struct something {const float m = 3} s;` //actually 12 members. Compiler doesn't accept values: "ISO C++ forbids initialization of member"
to fix above do
struct something {
something (float const& f = 3) : m(f)
const float m;
} s;
The difference between struct and class in C++ is that structs default their members to public while classes default to private (same goes for inheritance). That's all there is to it.
Then, in C++03 const float m = 3; is not valid as a member declaration. You would need to declare a constructor for your struct:
struct something
{
const float m;
const float n;
something() : m(3), n(42) {}
} s;
Structs AND classes in C++ suffer from this problem. You can only declare a value in a class definition if the variable is static and shared among all the instances of the class. If your variable is const I think that may be a good choice.
A good solution for non-const variables is a simple one - assign the desired values to all the variables in the default constructor of your class or struct.
e.g
struct Something
{
float value;
Something():value(5.0f) {};
}

How to initialize a struct with enum member?

I have a struct with many members and with different types (it's like 20 members):
enum TheEnum
{
FIRST = 0,
SECOND,
...
}
struct TheStruct
{
TheEnum z; // <--- the point !!! note that this is the first member (edited)
int a;
int b;
char c[32];
...
}
Due to there is an enum type member, I cant just declare like:
TheStruct Object = {0};
It will give compile error, but this initialization is the best way in my opinion.
The other ways that I can think of is:
1. ZeroMemory it, but I dont like this one.
2. Write a constructor, but this needs a lot of work.
3. Just don't initialize it.
So, is there any way to solve the enum problem? Should I pick a way in these 3?
Thanks!
EDIT:
My big mistake, the error only occurs when TheEnum presents as the first member.
Compiled using vs2008 and as C++ code.
The error is C2440. http://msdn.microsoft.com/en-us/library/sy5tsf8z%28v=VS.80%29.aspx
[edit] as the question changed
If you initialize a struct, you have to provide the correct types in your initializer.
In your case, the correct initialization would look like this:
TheStruct Object = {FIRST};
Your initialization list initializes the given number of struct members with what you have written and the rest of the struct with '0'.
Since your first member is an enum, you have to initialize that enum in this case.
[/edit]
there is nothing necessary. if you're compiling in C and not C++ just don't forget to write enum and struct and everything should work...
enum TheEnum
{
FIRST = 0,
SECOND,
...
}
struct TheStruct
{
int a;
int b;
char c[32];
...
enum TheEnum z; // <--- the point !!!
}
struct TheStruct Object = {0};
You can initialize the enum member just like any other. For example: TheStruct temp = {0,0,"", FIRST};

typedef struct : Default Initialization

typedef struct foo
{
bool my_bool;
int my_int;
} foo;
In the example above I understand that my_bool will be initialized randomly to either true or false but what about my_int? I assumed that my_int would be default initialized to 0 but that seems not to be the case.
Defining structs in this way appears to be incompatible with initialization lists so what is the best way to initialize my_bool and my_int to false and 0 respectively?
Types don't get "initialized". Only objects of some type get initialized. How and when they get initialized depends on how and where the corresponding object is defined. You provided no definition of any object in your question, so your question by itself doesn't really make much sense - it lacks necessary context.
For example, if you define a static object of type foo
static foo foo_object; // zeros
it will be automatically zero-initialized because all objects with static duration are always automatically zero-initialized.
If you define an automatic object of type foo without an initializer, it will remain uninitialized
void func()
{
foo foo_object; // garbage
}
If you define an automatic object of type foo with an aggregate initializer, it will be initialized in accordance with that initializer
void func()
{
foo foo_object1 = { 1, 2 }; // initialized
foo foo_object2 = {}; // initialized with zeros
}
If you allocate your object with new and provide no initializer, it will remain uninitialized
foo *p = new foo; // garbage in `*p`
But if you use the () initializer, it will be zero-initialzed
foo *p = new foo(); // zeros in `*p`
If you create a temporary object of type foo using the foo() expression, the result of that expression will be zero-initialized
bool b = foo().my_bool; // zero
int i = foo().my_int; // zero
So, once again, in your specific case the initialization details depend on now you create the object of your type, not on your type itself. Your type itself has no inherent initialization facilities and doesn't interfere with the initialization in any way.
Implement a default constructor:
typedef struct foo
{
foo()
: my_bool(false), my_int(0)
{
// Do nothing
}
bool my_bool;
int my_int;
} foo;
First off, the way that struct is declared is in the style of C. In C++ you should just do:
struct foo
{
bool my_bool;
int my_int;
};
In both C and C++, initialization is a separate step from allocation. If you always want to initialize the members of your struct, use default initialization syntax like this:
struct foo
{
bool my_bool{};
bool my_int{};
};
In older versions of C++ you need to manually write a default constructor that initializes all the members (the newer syntax above is just sugar for this):
struct foo
{
foo() : my_bool(), my_int() { }
bool my_bool;
int my_int;
};
As #sbi notes, if you want to manually initialize the struct, even without the default constructor, you can do foo myFoo = foo();
Have a default constructor:
struct foo {
foo() : my_bool(false), my_int(0) {}
bool my_bool;
int my_int;
};
You are not creating any object in that code. Initialization is done when you create objects, and is not particularly tucked by the way you declare the struct.
For instance the following initializes the boolean to false and the integer to 0
foo f = { };
Notice that you have just typdefed your struct. You have not created an object. Like others said you can omit the typedef in C++ and just declare the struct, and you are still able to refer to the type by just saying foo.
If you omit explicit initialization when you define an object, then for sure no initialization is done unless the object is defined at namespace scope or defined as static locally (in which case all members are zero-initialized) or the class has a user defined default constructor that does initialization accordingly.
As long as you are declaring the structs in a C-way, you could use zeromemory to null exactly sizeof(foo) bytes, therefore defaulting all values to 0.
In C++, you could define your structure with a constructor which would set your values to some default values if needed.
c and c++ don't initialize variables at all. They contain whatever happened to be in the memory location that they're now in previously. This also applies for member variables in classes and structs unless you specifically initialize them to a value.

How do you call a constructor for global objects, for arrays of objects, and for objects inside classes/structs?

How would you call the constructor of the following class in these three situations: Global objects, arrays of objects, and objects contained in another class/struct?
The class with the constructor (used in all three examples):
class Foo {
public:
Foo(int a) { b = a; }
private:
int b;
};
And here are my attempts at calling this constructor:
Global objects
Foo global_foo(3); // works, but I can't control when the constructor is called.
int main() {
// ...
}
Arrays of objects
int main() {
// Array on stack
Foo array_of_foos[30](3); // doesn't work
// Array on heap
Foo *pointer_to_another_array = new Foo(3) [30]; // doesn't work
}
There I'm attempting to call the constructor for all elements of the arrays, but I'd also like to know how to call it on individual elements.
Objects contained in classes/structs
class Bar {
Foo foo(3); // doesn't work
};
int main() {
Bar bar;
}
Global objects
Yours is the only way. On the other hand, try to avoid this. It’s better to use functions (or even other objects) as factories instead. That way, you can control the time of creation.
Arrays of objects
There’s no way to do this directly. Non-POD objects will always be default-constructed. std::fill is often a great help. You might also want to look into allocators and std::uninitialized_fill.
Objects contained in classes/structs
Use initialization lists in your constructor:
class Bar {
Foo foo;
Bar() : foo(3) { }
};
Static members must actually be defined outside the class:
class Bar {
static Foo foo;
};
Foo Bar::foo(3);
To correct some misconceptions about globals:
The order is well defined within a compilation unit.
It is the same as the order of definition
The order across compilation units is undefined.
The order of destruction is the EXACT opposite of creation.
Not something I recommend but: So a simple solution is to to put all globals into a single compilation unit.
Alternatively you can tweak the use of function static variables.
Basically you can have a function the returns a reference to the global you want (defining the global inside the function). It will be created on first use (and destroyed in reverse order of creation).
Foo& getGlobalA() // passed parameters can be passed to constructor
{
static Foo A;
return A;
}
Foo& getGlobalB()
{
static Foo B;
return B;
}
etc.
The Konrad reply is OK, just a puntualization about the arrays....
There is a way to create an array of items(not pointers) and here it follows:
//allocate raw memory for our array
void *rawMemory = operator new[](30 * sizeof(Foo))
// point array_of_foos to this memory so we can use it as an array of Foo
Foo *array_of_foos = static_cast<Foo *>(rawMemory);
// and now we can create the array of objects(NOT pointers to the objects)
// using the buffered new operator
for (int i = 0; i < 30; i++)
new(array_of_foos[i])Foo(3);
This approach is described here: http://www.amazon.com/gp/product/0321334876?ie=UTF8&tag=aristeia.com-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=0321334876
For the global case there is no way to control when it is called. The C++ spec essentially says it will be called before main() and will be destroyed sometime afterwards. Other than that' the compiler is free to do as it pleases.
In the first array case you are creating a static array of Foo objects. By default each value in the array will be initialized with the default constructor of Foo(). There is no way with a raw C++ array to force a particular overloaded constructor to be called. You can infer a bit of control by switching to a vector instead of an array. The vector constructor has an overloaded constructor vector(size,defaultValue) which should achieve what you are looking for. But in this case you must be careful because instead of calling Foo(3) it will call Foo(const Foo& other) where other is Foo(3).
The second array case is very similar to the first case. The only real difference is where the memory is allocated (on the heap instead of the stack). It has the same limitation with regards to calling to the constructor.
The contained case is a different issue. C++ has a clear separation between the definition of a field within an object and the initialization of the field. To get this to work in C++ you'll need to change your Bar definition to the following
class Bar{
Foo foo;
Bar() : foo(3){}
};
There seems to be the general gist in this thread that you cannot initialize members of an array other than using the default constructor. One answer even creates another type, just to call another constructor. Even though you can (if the array is not part as a member of a class!):
struct foo {
foo(int a): a(a) { }
explicit foo(std::string s): s(s) { }
private:
int a;
std::string s;
};
/* global */
foo f[] = { foo("global"), foo("array") };
int main() {
/* local */
foo f[] = { 10, 20, 30, foo("a"), foo("b") };
}
The type, however, needs to be copy-able: The items given are copy-initialized into the members of the array.
For arrays as members in classes, it's the best to use containers currently:
struct bar {
/* create a vector of 100 foo's, initialized with "initial" */
bar(): f(100, foo("initial")) { }
private:
std::vector<foo> f;
};
Using the placement-new technique described by andy.gurin is an option too. But note it will complicate things. You will have to call destructors yourself. And if any constructor throws, while you are still building up the array, then you need to figure where you stopped... Altogether, if you want to have arrays in your class, and want to initialize them, use of a std::vector is a simple bet.
Construction of arrays of objects:
You can modify your original example by using default parameters.
Currently only the default constructor is supported.
This is something that is being addressed by the next version (because everybody asks this question)
C++0X initializer lists solve this problem for the arrays of objects case. See this Herb Sutter blog entry, where he describes them in detail.
In the meantime you might be able to work around the problem like so:
class Foo {
public:
Foo(int a) : b(a) {}
private:
int b;
};
class Foo_3 : public Foo {
public:
Foo_3() : Foo(3) {}
};
Foo_3 array_of_foos[30];
Here, the Foo_3 class exists solely for the purpose of calling the Foo constructor with the correct argument. You could make it a template even:
template <int i>
class Foo_n : public Foo {
public:
Foo_n() : Foo(i) {}
};
Foo_n<3> array_of_foos[30];
Again this might not do exactly what you want but may provide some food for thought.
(Also note that in your Foo class you really should get into the habit of using member initializer lists instead of assignments in the constructor, as per my example above)
I reckon there are two ways to make sure global class objects' constructors are called safely at the time of their "creation":
Declare them in a namespace and make that namespace globally accessible.
Make it a global pointer to the class object and assign a new class object to it in main(), granted code for other global objects' constructors that access the object will execute before this.
Just my two cents.