I think I might have an oddly specific/weird question that I might be making more complex then it needs to be.
I have a simple class:
class Foo{
public:
struct Bar{
int otherdata;
};
int somedata;
};
In another file I import this class and create an Instance of Foo
I also want to create a vector of type Bar..how would I do this?
I have tried:
//Assume I already imported proper prereqs
int main() {
Foo test;
vector<test::Bar> vec;
//or
vector<test.Bar> vec;
//or
vector<Bar> vec;
}
Whats the best way to do this? I can simply do this if I take the struct and place it outside the class..but is there a way to encapsulate the struct and create a vector of that type of struct. I should point out that I do not want to initialize the vector inside the class, but rather in my main function.
Like this:
vector<Foo::Bar> vec;
You're looking for vector<Foo::Bar>.
The structure/class Bar will always have one int regardless of the instance of Foo, so it makes no sense (or at least it's redundant) to qualify it with test as in test::Bar or test.Bar. Hence, we qualify it as Foo::Bar.
Related
Sorry I ill formed the question earlier. The piece of code is something like:
class Bar
{
public:
// some stuff
private:
struct Foo
{
std::unordered_map<std::string, std::unique_ptr<Foo>> subFoo;
// some other basic variables here
};
Foo foo;
};
I got the basic idea about subFoo. But I am wondering that a single instance of Bar will contain only a single instance of Foo that is foo member variable? So a single instance/object of Bar will not be able to map multiple Foo inside the subFoo?
It feels like I am missing something here, can anyone break it down for me?
There are more misunderstandings about nested class definitions than there are actual benefits. In your code it really does not matter much and we can change it to:
struct Foo {
std::unordered_map<std::string, std::unique_ptr<Foo>> subFoo;
// some other basic variables here
};
class Bar
{
Foo foo;
};
Foo is now defined in a different scope and it is no longer private to Bar. Otherwise it makes no difference for the present code.
I am wondering that a single instance of Bar will contain only a single instance of Foo that is foo member variable?
Yes.
So a single instance/object of Bar will not be able to map multiple Foo inside the subFoo?
subFoo is a map holding unique pointers to Foos. Bar::foo is not managed by a unique pointer, hence placing them in subFoo is not possible without running into a double free error. std::unique_ptr can be used with a custom deleter, but thats not the case here. Hence you cannot store a unique pointer to Bar::foo in any Foo::subFoo. You can however, store unique pointers to other Foos in Foo::subFoo.
Let's assume I have the following code:
typedef struct foo{
int x;
}foo;
typedef struct bar{
int y
}bar;
struct foobar{
std::vector<foo> foo1;
std::vector<bar> bar1;
};
Is there any way to change std::vector<bar> bar1; into std::vector<foo> bar1; and erase any data inside?
And if so, could this be done in a function? Something like this?
replaceBar(&myOwnStruct);
I am not too great with vectors, so an explanaitaion to why this is/isn't possible would be nice.
Thanks!
The way to "change" a variable's type (which is not really possible in C++) from one type to another is to use std::variant to indicate the possible types it is allowed to hold (or, use std::any to hold all types), eg:
std::variant<std::vector<bar>, std::vector<foo>> bar1;
You could then have bar1 hold a std::vector<bar> initially, and then at a later time reassign it to hold a std::vector<foo> instead.
struct foo{
int x;
};
struct bar{
int y;
};
struct foobar{
std::vector<foo> foo1;
std::variant<std::vector<bar>, std::vector<foo>> bar1;
};
void replaceBar(foobar *fb) {
fb->bar1 = std::vector<foo>{};
}
foobar myOwnStruct;
foobar.bar1 = std::vector<bar>{};
replaceBar(&myOwnStruct);
Possibility 1: If foo and bar can have a common base class.
You could then have the vector be of pointers to the base class. You can then re-point the pointer to a different object. But it will reallocate memory. Not exactly what you wanted.
Possibility 2: You could declare a union. But note that the vector's memory is on heap so it doesnt really achieve your objective and you'll have to be careful about destructors. If it were plain object arrays with fixed sizes, you could do it.
Possiblity 3: This may work for you in games. Instead of storing a vector directly, store a flatbuffers serialized block of bytes. You can rewrite a different thing into those bytes. You'll need another variable in the struct to say what's in those bytes. Maybe this option is too far out there for you !
What I am trying to achieve is create a template of a struct myVector which would contain two vectors i.e. vector_a and vector_b. But i am quite new to templates. I mean, I know why and when one would prefer using Templates in certain situations but I am not quite sure how to tackle this problem. What I have written is:
'''
#include<iostream>
#include<stddef.h>
#include<vector>
template <typename T> struct myVector {
std::vector<T> vector_a;
std::vector<T> vector_b;
};
int main() {
myVector<int> z1(5);
myVector<int> z2(6);
}
'''
I end up getting errors like no matching function for call to ‘VectorXY::VectorXY(int)’
for the vector VectorXY z2(6);
Therefore, I would really appreciate your help. Thanks in advance.
Your error has nothing to do with templates. Consider the following code
struct Int { int i; };
int main()
{
Int z(1); // doesn't compile
}
and you get the error, no matching constructor Int(int).
Classes are an abstraction over something else. It might seem obvious that an int and an Int in this case are the same thing, and constructing one should be like constructing the other. But the compiler doesn't know that, so you need to provide a constructor that passes the argument onto the member.
struct Int
{
int i;
Int(int n) : i(n) {}
};
Note that in C++20, the compiler will actually be able to figure out that you want to use each constructor argument to initialize the corresponding member of your class, so even without a provided constructor, the Int will work like an int.
However, even in that case, your code would not work, since you need to use more complicated rules to construct your members. In your case, you'll need something like
myVector(int n) : vector_a(n), vector_b(n) {}
Assuming that you want the internal vectors to be constructed with the value passed into the constructor. Based on your calling code, it seems that's what you want, but you can write any logic in the constructor.
I am creating a bunch of C structs so i can encapsulate data to be passed over a dll c interface. The structs have many members, and I want them to have defaults, so that they can be created with only a few members specified.
As I understand it, the structs need to remain c-style, so can't contain constructors. Whats the best way to create them? I was thinking a factory?
struct Foo {
static Foo make_default ();
};
A factory is overkill. You use it when you want to create instances of a given interface, but the runtime type of the implementation isn't statically known at the site of creation.
The C-Structs can still have member functions. Problems will, however, arise if you start using virtual functions as this necessitates a virtual table somewhere in the struct's memory. Normal member functions (such as a constructor) don't actually add any size to the struct. You can then pass the struct to the DLL with no problems.
I would use a constructor class:
struct Foo { ... };
class MakeFoo
{
Foo x;
public:
MakeFoo(<Required-Members>)
{
<Initalize Required Members in x>
<Initalize Members with default values in x>
}
MakeFoo& optionalMember1(T v)
{
x.optionalMember1 = v;
}
// .. for the rest option members;
operator Foo() const
{
return x;
}
};
This allows to arbitrary set members of the struct in expression:
processFoo(MakeFoo(1,2,3).optionalMember3(5));
I have an easy idea, here is how:
Make the structure, just like you normally would, and create a simple function that initializes it:
struct Foo{...};
void Default(Foo &obj) {
// ... do the initialization here
}
If you have multiple structures, you are allowed in C++ to overload the function, so you can have many functions called 'default', each initializing its own type, for example:
struct Foo { //... };
struct Bar { //... };
void Default(Foo &obj) {...}
void Default(Bar &obj) {...}
The C++ compiler will know when to call the first or the second overload based on the parameter. The & makes obj a reference to whatever parameter you give it, so any changes made to obj will be reflected to the variable you put as parameter.
Edit:
I also have an idea for how to specify some parameters, you can do it by using default parameters. This is how it works:
For example you the following function; you can specify default values for parameters like this:
void Default (Foo &obj, int number_of_something = 0, int some_other_param = 10)
{ ... }
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.