Initialize array of class objects in constructor of another class - c++

If I have a class:
class A
{
private:
char z;
int x;
public:
A(char inputz, int inputx);
~A() {}
}
I want to make an array of A in class B.
class B
{
private:
A arrayofa[26];
public:
B();
~B() {}
void updatearray(); // This will fill the array with what is needed.
}
class B
{
B:B()
{
updatearray();
std::sort( &arrayofa[0], &arrayofa[26], A::descend );
}
}
How do I explicitly initialize arrayofa in the constructor of B?

The default constructor will be called automatically (for non-POD). If you need a different constructor you're out of luck, but you can use vector instead which will support what you need.

You can't.
Each element in the array will be initialized by the default constructor (no parameter constructor).
The best alternative is to use a vector.
Here you specify an a value that will be copy constructed into all members of the vector:
class B
{
private:
std::vector<A> arrayofa;
public:
B()
: arrayofa(26, A(5,5))
// create a vector of 26 elements.
// Each element will be initialized using the copy constructor
// and the value A(5,5) will be passed as the parameter.
{}
~B(){}
void updatearray();//This will fill the array with what is needed
}

First there should be a default constructor for class A, else B() will not compile. It will try to call the default constructor of members of class B before the body of the constructor starts executing.
You can initialize arrayofa like this:
void B::updatearray()
{
arrayofa[0] = A('A', 10);
arrayofa[1] = A('B', 20);
...
}
It would be better to use std::vector instead of array.
std::vector<A> v(26, A('a', 10)); //initialize all 26 objects with 'a' and 10

Related

Is there a way to initialize a member object of a class within the constructors code instead of the initializer list?

Consider I want to wrap some library code inside an object. That library needs to be set up and initialized by calling some function inside the constructor of that wrapper class.
The librarie's "objects" then diverge into creating more, different "objects" that the wrapper class wraps in form of yet another wrapper object that should be a plain member of that class.
But as far as I see it, members of classes can only be initialized or created by calling their constructor in the initalizer list of the constructor. The execution of these bits of code preceed the constructor of the actual class that does the initialization of the library and its environment, making it impossible for me to actually initialize that member object as a member and instead force me to initialize it as a pointer to the 2nd wrapper, because its constructor must be called manually within the first constructor's code.
Example:
class A {
public:
A() {
if(!wrapped_library_init()) {
exit(CRITICAL_ERROR);
}
ptr_to_some_library_metadata *a = library_function(); /*Needs to
be called after wrapped_library_init() or needs a pointer to some
wrapped object created inside this constructor */
//initialize b
}
private:
B b; //Wants to be a member but can not
};
class B {
B(ptr_to_some_library_metadata *a);
}
Member objects can only be constructed in the member initializer list. There are a few techniques which can be used to make it possible to initialize an object, though:
Use a helper [lambda] function doing the necessary extra work before return a suitable object. For example:
A()
: B([]{
if (!wrapped_library_init()) {
exit(CRITICAL_ERROR);
}
return library_function();
}()) {
}
You can delay construction by using a union with just the appropriate member. When using this technique the member needs to be explicitly destructed, for example:
class A {
union Bu { B b };
Bu b;
public:
A() {
if (!wrapped_library_init()) {
exit(CRITICAL_ERROR);
}
new(&b.b) B(library_function());
}
~A() {
b.b.~B();
}
// ...
};
I'd personally use the first approach. However, there are cases when using a union to delay construction is helpful.
Initializer lists are there to use another constructor than the default constructor.
But nothing impedes you for creating a custom function that will initialize b:
class A {
public:
A():b(init()) {
}
private:
B b; //Wants to be a member but can not
static B init()
{
if(!wrapped_library_init()) {
exit(CRITICAL_ERROR);
}
ptr_to_some_library_metadata *a = library_function(); /*Needs to
be called after wrapped_library_init() or needs a pointer to some
wrapped object created inside this constructor */
return B(a);
}
};
Wrap your library inside a class:
class LibraryWrapper
{
public:
LibraryWrapper()
{
if(!wrapped_library_init()) {
exit(CRITICAL_ERROR);
}
lib_data.reset(library_function()); /*Needs to
be called after wrapped_library_init() or needs a pointer to some
wrapped object created inside this constructor */
}
//~LibraryWrapper() {/**/}
//LibraryWrapper(const LibraryWrapper&) {/**/} // =delete; ?
//LibraryWrapper& operator=(const LibraryWrapper&) {/**/} // =delete; ?
//private: // and appropriate interface to hide internal
std::unique_ptr<ptr_to_some_library_metadata, CustomDeleter> lib_data;
};
class B {
public:
explicit B(ptr_to_some_library_metadata *a);
// ...
};
And use extra member or inheritance:
class A
{
public:
A() : b(lib.lib_data.get()) {}
private:
LibraryWrapper lib; // placed before B
B b;
};

c++ class in a class default constructor

My concern is a default constructor and its initialisation list. In a simple case it's clear, like:
class A
{
protected:
double d1;
//classB obj1; //how to initialize this one in a default constructor?
public:
A (double x = 0.0): d1(x){} //constructor
virtual ~A(void) {};
//something
}
But how to initialize the object of classB, which has a big amount of members? Or how in general initialize in default constructor some type that has a big or unknown amount of parameters to be initialized?
You could initialize obj1 in member initializer list by calling its default constructor or other constructors
class A
{
protected:
double d1;
classB obj1;
pthread_mutex_t m_mutex;
public:
A (double x = 0.0): d1(x), obj1(), m_mutex(PTHREAD_MUTEX_INITIALIZER) {}
virtual ~A(void) {}
//something
}
if classB has big of members like you described, you may break the rule of class design - one class does one thing. You might want to break classB into small independent classes.
If you want to explicitly initialize an object, just add it to the constructor initializer list:
struct Foo
{
Foo(int arg) { ... }
};
struct Bar
{
Foo foo;
Bar()
: foo(123) // Initialize `foo` with an argument
{ ... }
};
If the member can be initialized by its default constructor, then it doesn't even have to be in the initialization list, because a default constructor doesn't have parameters. The default constructor will be called. Primitives don't have default constructors so they have to be in the initialization list if you want to have them initialized.

c++ how to write a constructor?

I'm not used to c++ and I'm having a problem writing a constructor.
See this example, is a short version of the code I'm working on:
class B {
public:
B(int x);
}
class A {
public:
B b;
A(){
// here I have to initialize b
}
}
That throws a compiler error since I need to initialize b in A's constructor because B does not have a default constructor.
I think I have do it in the initialization list, but the B(int x) argument is a value I have to calculate with some algorithm, so I don't know how this should be properly done, or if I'm missing something or doing it wrong.
In other language like java I would have a reference to B and initialize it inside the A's constructor after the other code I need to get the value for the initialization.
What would be the right way to initialize b in this case?
Thanks!
You can invoke functions in your constructor initializer list
class B {
public:
B(int x);
}; // note semicolon
class A {
public:
B b;
A()
:b(calculateValue()) {
// here I have to initialize b
}
static int calculateValue() {
/* ... */
}
}; // note semicolon
Note that in the initializer list, the class is considered completely defined, so you can see members declared later on too. Also better not use non-static functions in the constructor initializer list, since not all members have yet been initialized at that point. A static member function call is fine.
You use an initializer list, something like this:
A() : b(f(x)) {}
#include<iostream>
class B {
public:
B(){} // A default constructor is a must, if you have other variations of constructor
B(int x){}
}; // class body ends with a semicolon
class A {
private:
B b;
public:
A(){
// here I have to initialize b
}
void write(){
std::cout<<"Awesome";
}
};
int main(){
A a;
a.write();
}
In C++, if you have a constructor that takes an argument, a default constructor is a must, unlike other languages as Java. That's all you need to change. Thanks.

OOP Constructor question C++

Let's say that I have two classes A and B.
class A
{
private:
int value;
public:
A(int v)
{
value = v;
}
};
class B
{
private:
A value;
public:
B()
{
// Here's my problem
}
}
I guess it's something basic but I don't know how to call A's constructor.
Also the compiler demands a default constructor for class A. But if A has a default constructor than wouldn't the default constructor be called whenever I declare a variable of type A. Can I still call a constructor after the default constructor has been called? Or can I declare an instance of a class and then call a constructor later?
I think this could be solved using pointers but can that be avoided ?
I know that you can do something like this in C#.
EDIT: I want to do some computations in the constructor and than initialize the classes. I don't know the values beforehand.
Let's say I'm reading the value from a file and then I initialize A accordingly.
The term you are looking for is initializer list. It is separated from the constructor body with a colon and determines how the members are initialized. Always prefer initialization to assignment when possible.
class A
{
int value;
public:
A(int value) : value(value) {}
};
class B
{
A a;
public:
B(int value) : a(value) {}
}
I want to do some computations in the constructor and than initialize the classes. I don't know the values beforehand.
Simply perform the computation in a separate function which you then call in the initializer list.
class B
{
A a;
static int some_computation()
{
return 42;
}
public:
B() : a(some_computation()) {}
}
You use an initialization list to initialize the member variables.
public:
B() : value(4) { // calls A::A(4) for value.
}
Or can I declare an instance of a class and then call a constructor later?
Yes, you can do that. Instead of (A value;) declare (A* value;), and then B's constructor will be B():value(new A(5)){}.
In the B's destructor you will have to do delete value;
I think this could be solved using pointers but can that be avoided ?
Yes. Use shared_ptr.
Try:
B() :
value(0)
{
// Here's my problem
}

Constructor initialising an array of subobjects?

Say I have several objects within a class, each of which needs constructing with a different value. I can write something like this:
class b
{
public:
b(int num)
{
// 1 for a.b1, and 2 for a.b2
}
};
class a
{
public:
b b1;
b b2;
a() : b1(1), b2(2)
{
}
};
However, is it possible to do the same thing if those multiple objects are stored in an array?
My first attempt at it doesn't compile:
class a
{
public:
b bb[2];
a() : bb[0](1), bb[1](2)
{
}
};
You cannot do this directly; you need to initialize the array elements in the body of the constructor.
The elements of the array are default constructed before the body of the constructor is entered. Since your example class b is not default constructible (i.e., it has no constructor that can be called with zero parameters), you can't have an array of b as a member variable.
You can have an array of a type that is not default constructible in other contexts, when you can explicitly initialize the array.