Declare and initialise an array of struct/class at the same time - c++

1.
I know that it is possible to initialise an array of structures in the declaration. For example:
struct BusStruct
{
string registration_number;
string route;
};
struct BusStruct BusDepot[] =
{
{ "ED3280", "70" },
{ "ED3536", "73" },
{ "FP6583", "74A" },
};
If the structure is changed into a class, like this:
class BusClass
{
protected:
string m_registration_number;
string m_route;
public:
// maybe some public functions to help initialisation
};
Is it possible to do the same as for the structure (i.e. declare and initialise an array of classes at the same time)?
2.
Am I correct to think that it is not possible to declare and initialise vector<BusStruct> or vector<BusClass> at the same time?

Is it possible to do the same as for the structure (i.e. declare and initialise an array of classes at the same time)?
Not unless you create a suitable constructor:
class BusClass
{
protected:
string m_registration_number;
string m_route;
public:
// maybe some public functions to help initialisation
// Indeed:
BusClass(string const& registration_number,
string const& route)
:m_registration_number(registration_number),
m_route(route) { }
};
Or you make all members public and omit the constructor, in which case you can use the same initialization syntax as for the struct. But i think that's not what you intended.
Am I correct to think that it is not possible to declare and initialise vector<BusStruct> or vector<BusClass> at the same time?
No it's not possible with current C++. You can however use libraries that make this possible. I recommend Boost.Assign for that. For that, however, your class has to have a constructor, and likewise your struct too - Or you need to create some kind of factory function
BusStruct make_bus(string const& registration_number,
string const& route) { ... }
If you want to keep the struct initializable with the brace enclosed initializer list in other cases.

No, you would not be able to initialize classes the way you can with structures. But you can write the class constructor inside the array declaration.
C++ has no built in way of initializing vectors, unless you want to load the vector from an array that you have initialized.

C++ natively supports two forms of vector initialization and neither is what you are looking for.
1: Every element the same as in:
vector<int> ints(4,1000); //creates a vector of 4 ints, each value is 1000.
2: Copy from an existing vector as in:
vector<int> original(3,1000); //original vector has 3 values, all equal 1000.
vector<int> otherVector(original.begin(),original.end()); //otherVector has 3 values, copied from original vector

Related

Inner Class Accessing Parent from a Global Variable

How can I improve the structure of the code below?
I have a nested class. I want to access the parent class which is available as a global vector. The ugly part is when I store the index of the parent class in the child class. Can I do better?
vector<A> vec;
struct A
{
int val;
struct B
{
size_t id; // Index of the parent in the global vector. Doesn't look good!
void func()
{
cout << vec[id].val;
}
};
B b;
};
int main()
{
A a;
a.b.id = vec.size() - 1; // Also ugly!
vec.push_back(a);
}
Firstly you should not make use of global variables at all. It is quite bad practice, as any variable lacking access specification can be altered at any point by the program.
This is not so much of an issue with a small program such as this, but in bigger projects you might end up with some very nasty bugs if you were to continue using global variables.
Next, it makes sense to redefine this struct. There is no explicit rule, but in my opinion a struct should not really contain anything other than data members. It would instead be better to define a class, perhaps containing a struct similar to struct b if that is what you wanted. Personally however that is not how I would approach this problem.
Consider instead defining a class A, you might have a variable for "value". Then you might define a function that is passed a value that you want to assign that assigns a value to the "value" variable of that class.
Then within main you might instantiate a vector of "A"s, then set up a for loop(or some other kind of loop it is your choice after all). That for loop can then iterate however many times you tell it to. Per iteration you could instantiate an "A" object, initialise the value within the object, and then push the object onto the back of the vector of "A"s.
At any point within the scope of the main function you can iterate by another for loop through the vector of "A"s to access by index the the "A" object that is required, through which the value can also be accessed. So long as your for loop is set up to begin iterating from a count of 0, the index value for each element of the vector of "A"s will be the same as the the for loop's control variable at each iteration.
The approach that has been outlined is not the optimal solution, however as with all programming there are a number of solutions to your problem and it is up to you to find which is best. Given the context provided it makes sense not to confuse you further by overloading you with information but there are many ways to improve the potential solution outlined above.
Hopefully this answer shows you another path to the same destination, that perhaps is a little bit cleaner and more manageable. Furthermore as a first time responder I hope I have not made any mistakes myself(please let me know if I messed anything up here other readers)! Good luck with your programming!
I think you will need to pass a pointer of the enclosing class to the nested class to be able to use the enclosed class's non-static members.
See the PIMPL idiom for example here:
Why would one use nested classes in C++?
Could write classes like this:
#include <iostream>
#include <memory>
struct A
{
int val;
int getv() {return val;}
struct B
{
A * my_parent;
B(A * a) : my_parent(a) {}
void func()
{
std::cout << my_parent->val << std::endl;
}
};
std::unique_ptr<B> b;
A();
};
A::A() : b(new B(this)) {}
int main()
{
A a;
a.val = 1;
a.b->func();
}

How to use common values in many objects in C++?

I need to instantiate many objects from a class, but each one of them needs to be aware of a certain value X that is common for every object of this class, like a global parameter. This is necessary for my constructors to work properly in my objects.
Is there a way to do that without passing the value as a constructor parameter? What I wanna do is use the same variable in all objects so I don't waste RAM.
*in my real situation it's not just an X value, is a 1024-dimmension int vector.
What you want is a static member. "When a data member is declared as static, only one copy of the data is maintained for all objects of the class". e.g.
class myClass {
public:
static int x;
};
I assume you mean that you want a vector of size 1024 as the shared variable across all your classes. You could do this:
class MyClass {
static std::vector<int> s_my_vector;
}
This code would go into your header file. In your cpp file, you'd have to initialize the std::vector. However, I do not recommend this. Class static variables that require constructor calls (i.e. not primitives or POD types) have a lot of gotchas that I'm not planning to go into. I will offer a better solution however:
class MyClass {
static std::vector<int> & GetMyVector()
{
static std::vector<int> my_vector;
static bool initialized = MyVectorInit(my_vector);
return my_vector;
}
static bool MyVectorInit(std::vector<int> & v)
{
v.resize(1024);
...
}
public:
MyClass() {
std::vector<int> & v = GetMyVector();
...
}
static void EarlyVectorInit()
{
GetMyVector();
}
}
In this case, the static local variable ensures that there will only be one copy of my_vector, and you can get a reference to it by calling GetMyVector. Furthermore, the static bool initialized is guaranteed to only be created once, which means that MyVectorInit will only be called once. You can use this method in case you need to populate your vector in some non-trivial way that can't be done in the constructor.
The way I've written it, your vector will be created automatically the first time you need to use it, which is fairly convenient. If you want to manually trigger creation for some reason, call EarlyVectorInit().

2D struct array member variable with varying sizes

So I've got a class that I'm generalizing into a base class. One of the member variables is a 2D array of a struct.
struct SomeType
{
...
}
and then in the class's header:
SomeType member_variable_ [SIZE_ONE][SIZE_TWO];
But, in my situation, SIZE_TWO needs to be set when the class is initialized because it's going to be different depending on what's using this. What's the best way to have a 2D struct array with a size that's not yet set as a member variable?
The simplest way to solve it is to not use C-style arrays at all, but to use std::vector. Or possibly an std::array of vectors:
std::array<std::vector<SomeType>, SIZE_ONE> member_variable_;
Now you can easily insert as many (or as few) SomeType objects as needed, and still use the array-indexing syntax:
member_variable_[some_index][some_other_index]
To set a fixed size at runtime for the "second" Dimension, you can do something like this in the constructor:
for (auto& v : member_variable_)
v = std::vector<SomeType>(the_runtime_size);
You could use a template:
template<unsigned SIZE_TWO>
class theClass
{
SomeType member_variable_ [SIZE_ONE][SIZE_TWO];
SIZE_TWO will be set when you instantiate the class.
theClass<5> tc; //member_variable_ [SIZE_ONE][5];
You could also use containers like std::vector or std::array.

Declaring array in class and using it

I want to create an array in class hash and use it in its methods. I tried declaring it in public but still other methods are not able to access it.
Here is my class declaration:
class hash
{
public:
string hash_table[size]; //size is global variable;
void initialize(int,string*,int); //I pass `hash_table` pointer and two other `int` type //arguments.
int hash_function(string, int);
void quad_prob(int, int, string* , string); //`hash_table` array is used in this method also.
void print(string*); //to print `hash_table` array
};
I have to use array only.
Also, can pleas explain when I use hash h; in int main(), what happens?
Here is complete code (without using class structure) : http://codepad.org/DQggdoI6
It looks like you are trying to convert existing code to a class, yes? Keep your string hash_table[] private in the class. Then remove that parameter from each of the functions on codepad. So initialize, as folks have pointed out, becomes the constructor hash(int n, int size) and initializes hash_table (hash_table = new string[size] or some such). Similarly, print becomes just plain print(), and can refer directly to hash_table since it's a member function of the hash class.
your array will be initialized when you create a new hash object. You would use hash h before any code using the object. When you make a new object, your constructor sets up your object for later use in your code. From there you should be able to use your code from your class.
first I would suggest you use a vector.
Secondly once its defined in your class you just access it by name.
class foo
{
public:
foo(): vecfoo(5)
{}
void DoSomeThing()
{
for_each(begin(vecfoo),end(vecfoo),[](const string &){...});
}
private:
vector<string> vecfoo;
};

Variable amount of function arguments in C++

So, in C the standard way is stdarg.h. But I'm looking to pull up something a bit like this:
template<int A>
class MyClass {
public:
MyClass(...) {
// fill each value of array with an argument.
};
virtual ~MyClass() { };
private:
float array[A];
};
Obviously, the idea is not to have different constructions for every possible amount of arguments. Any suggestions, standard ways, whatsoever?
Thanks,
Julian.
In C++11 you can use an std::initializer_list constructor for this kind of scenario. That allows for this type of initialization:
MyClass<5> x{1,2,3,4,5};
although you have to define what happens when the dimensions do not match. But for these kinds of statically sized arrays, it is worth looking at std::array. These have a well defined behaviour when the dimensions of the initializer don't match their own.
you need to use initializer_list
explicit MyClass(std::initializer_list<T> list_args){
// fill each value of array with an argument.
};
If you don't have access to C++11 initializer_lists you can just pass a vector.
MyClass(const std::vector& values) {
//copy values into array
};
MyClass someClass( std::vector<int>(10,4) ); //adds 10x 4 to the vector