OOP Constructor question C++ - 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
}

Related

Why can't I use a class object as a parameter

I have this problem with getting class to pass as a parameter for another class constructor. Basically the code is like this:
class A
{
public:
int ID;
A(int getID)
{
ID = getID;
}
}
and I want to use that class A as a member of class B like this:
class B
{
public:
A someA;
A someB;
int number;
B(A ObjectA, A ObjectB, int getNumber)
{
someA = ObjectA;
someB = ObjectB;
number = getNumber;
}
};
The errors are basically saying that there is no matching function to call B::B(). I don't know whats wrong with it. I have done similar things with vectors of object, so I thought why cant this thing works. Any inputs/correction is appreciated, thank you!
Sidenotes: I have tried adding a default constructor for B as suggested in another thread, but it ended up saying invalid use of B::B.
Use the initialization list for your objects:
B(A ObjectA, A ObjectB, int getNumber)
:someA(std::move(ObjectA)), someB(std::move(ObjectB)), number(getNumber)
{
}
This will use the default move constructor from your class.
I used move here because you are passing your objects by value, so it makes sense to move them. If you passed them by const&, then don't move them and use the default copy constructor.
Still, this is about A default constructor, there is no problem with the B default constructor in the code you showed.
The error happens because you didn't tell B how to initialize its A attributes, so it's looking for the default A constructor.
In C++ the attribute initialization is made as show by Matthieu, and not in the constructor's body. You can add a default A constructor, but you have to think if it's the behavior you want for your code.
Compiling the code below doesn't show any error.
class A {
public:
int ID;
A() {}
A(int getID) {
ID = getID;
}
};
class B {
public:
A someA;
A someB;
int number;
B() {}
B(A ObjectA, A ObjectB, int getNumber) {
someA = ObjectA;
someB = ObjectB;
number = getNumber;
}
};

Initialize members with deleted default constructor

In C++, if I want to have a member of a class that has no default constructor, I need to explicitly initialize it like this:
class a
{
a(int)
{
}
};
class b
{
a x;
b() : x(3)
{
}
};
However, sometimes the initialization for, say, x, could not be so simple. It could either be a very very complicated formula or a whole, algorithmic function with fors and ifs that needs to be computed. I usually solve it like this:
class b
{
a * x;
b()
{
// Do some very complicated computations
this->x = new a(result_of_complicated_computations);
}
};
Which, however, forces me to delete the pointer at the moment of destruction, it slightly less performing and makes my code somehow untidy and ugly. I am really surprised that there is no way to compute parameters for constructors of members within the constructor of the class, without having to use this kind of tricks.
Are there more elegant solutions to this?
Use a helper function:
class b
{
a x;
b() : x(complicated_computation()) { }
private:
static int complicated_computation() {
return result_of_complicated_computations;
}
};
And the default-constructor isn't deleted, but undeclared.
Do the computations in a function:
static a complicated_computations();
b() : x(complicated_computations()) {}
I don't get it. If you have:
class A
{
private:
//a lot of members
public:
A(/* complex object used for construction */)
: //initialize members
{ }
}
You can simply do:
class B
{
private:
A a;
public:
B()
: a(call_to_function_that_generates_this_complex_data())
{ }
};
You can even use your member functions during construction. But note, that:
ยง 12.6.2.13:
Member functions (including virtual member functions,
10.3) can be called for an object under construction.(...) However, if these operations are performed in a ctor-initializer (or in a function
called directly or indirectly from a ctor-initializer) before all the
mem-initializers for base classes have completed, the result of the
operation is undefined.

declaring a class with a nondefault constructor inside another class

How can I achieve this behavior?
class A
{
int x;
public:
A(int x) : x(x) {}
};
class B
{
A a; // here is the problem
public:
B() : a(1) {} // solution i found
};
int main(void)
{
B b;
return 0;
}
I'm wondering if there is another way of making this work except the answer I found.
No. That's the proper solution. You explicitly state you don't want it to be possible to initialize A with no parameters, so this outcome shouldn't surprise you.
Or provide a default for x:
class A
{
int x;
public:
A(int x = 1) : x(x) {}
};
making it a default constructor.
Add a second, default constructor to A:
class A
{
int x;
public:
A(int x) : x(x) {}
A() : x(1) {}
};
Yes, in C++11, you could just write this:
class B
{
A a(1); //C++11 support this! (though the compilers may not, now)
public:
B() {} //nothing here!
};
Or this,
A a{1}; //using uniform initialization
You should remember that when you add one constructor explicitly then default constructor will be not created automaticly. It is a only a default constructor. Copy constructor will be created.
Also remember of rule of three:
The rule of three (also known as the Law of The Big Three or The Big Three) is a rule of thumb in C++ that claims that if a class defines one of the following it should probably explicitly define all three[1]:
destructor
copy constructor
copy assignment operator
>
I'm sure you already know this but you can make "a" a pointer to an object of type A: that will allow you to control when the object is instantiated, and thus what value can be passed into the A constructor at run time (will require deletion obviously)

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.

Can constructor call another constructor in c++?

class A{
A(int a = 5){
DoSomething();
A();
}
A(){...}
}
Can the first constructor call the second one?
Not before C++11.
Extract the common functionality into a separate function instead. I usually name this function construct().
The "so-called" second call would compile, but has a different meaning in C++: it would construct a new object, a temporary, which will then be instantly deleted at the end of the statement. So, no.
A destructor, however, can be called without a problem.
Not before C++0x, no.
BUT, just out of academic interest I've come up with a really horrible way* to do it using a placement operator "new" (someone care to point out how portable this is?)
#include <new>
#include <iostream>
class A
{
public:
A(int i, int j)
: i_(i), j_(j) { }
A(int i)
{ new (this) A(i, 13); }
int i_,j_;
};
int
main() {
A a1(10,11), a2(10);
std::cout
<< a1.i_ << ", "
<< a1.j_ << std::endl
<< a2.i_ << ", "
<< a2.j_ << std::endl;
return 0;
}
*Hell no, I don't write this in the production code.
The answer is in fact "yes", but as others have suggested, it doesn't do what you want. You can of course use the constructor of a base class, either implicitly or explicitly:
struct B {
B() {}
B( int x ) {}
};
struct A : public B {
A() {} // calls B() implicitly
A( int a, int b ) : B( b ) {} // calls B(int) explicitly
};
Not directly. There are a few ways to work around this.
From the initializer list of your class' constructor, you can call a constructor on any base class, and on all member variables.
So you can usually refactor your class and split it into several smaller ones to solve the problem. The commonly executed code can be placed in a member object or perhaps a base class. Then each of the main class' constructors just have to decide which construcotr to use to initialize that member.
class B {
B() { }
B(int b) { DoSomething(); }
}
class A{
A(int a = 5) : b(a) { } // call B's constructor which does something
A() : b() {} // call B's constructor which does nothing
B b;
};
This is an old question; however,
class A{
A(int a = 5){
DoSomething();
A();
}
A(){...}
}
could be
class A{
A(int a = 5){
*this = A();
DoSomething();
}
A(){...}
}
As pointed out by Pavel Radzivilovsky in his answer, since C++ 11, it is possible. It is the same syntax as for explicitely calling the parent's class constructor from a child class. This is useful when a class needs to have multiple constructors (say, a default constructor and a constructor with attribute initialization) but some operations have to be done in all cases. This allows to avoid code repetitions.
Here is an example:
class A
{
public:
A()
{
foo();
}
A(Attribute attribute) : A()
{
this->attribute = attribute;
}
//------ some other code --------
private:
Attribute attribute;
void foo()
{...}
//------ some other code -------
};
In this simple example, I assume that the function foo() needs to be called in all cases for the object to be correctly initialized. With this syntax, if the second constructor (with attribute initialization) is called, it will first perform the operations in the default constructor before executing the instructions in the attribute-initialization constructor.
It can also be done the other way around: the default constructor can call another constructor with default parameters.
Before C++ 11, it was necessary to duplicate the common instructions of all constructors or define methods that do the actual object initialization.