How are member instances in C++ constructed? [duplicate] - c++

This question already has answers here:
What is this weird colon-member (" : ") syntax in the constructor?
(14 answers)
No matching function for call to Class Constructor
(5 answers)
Closed 5 years ago.
I have a class called A.
It has an instance or B:
public:
B inst;
B's constructor is like B::B(int, int).
When creating the A class's constructor A::A() { }, it gives me the following error:
No matching function for call to B::B()
when I haven't created or mentioned any B in A's constructor. Any idea?

Constructing A requires all of A's data members to be constructed. In this case, B must be default-constructed as you did not provide a member initialization list. As B defines a non-default constructor, generation of its implicit default constructor is suppressed - that's why you're getting the error.

When class A contains an instance of class B, constructing an instance of A also requires construction of the contained instance of B.
If no constructor of B is listed in the initialiser of class A, the default is to invoke a constructor of B that accepts no arguments. For example
class A
{
public:
A::A() {};
private:
B b;
};
is functionally equivalent to
class A
{
public:
A::A() : b() {};
private:
B b;
};
This involves a constructor of B with no arguments. If no such constructor exists, the result is a diagnostic (error message). Since you have declared/defined a constructor with arguments, a constructor for B with no arguments is not implicitly generated.

Related

Declaring an object with a parameterized constructor inside another class C++ [duplicate]

This question already has answers here:
C++ class member with constructor
(4 answers)
Avoid default constructor for member variable
(2 answers)
Explicitly initialize member which does not have a default constructor
(4 answers)
Closed 2 years ago.
I wish to have an object of one class contained inside a different class.
class A contained inside class B as in the simple example below.
The problem is that class A only has a parametrized constructor.
Is there another way to do declare the class A object in class B without having to use a pointer to class A ?
class A
{
public:
A(int var1, int var2);
private:
//...
};
class B
{
public:
B();
private:
A a; // Compiler error
A* a_ptr; // This will of course work fine. We can create a new A object with parameters any time using the a_ptr
};
A a; // Compiler error
except if the constructor of B explicitly calls the constructor of A with required arguments (e.g. B() : a(an_int, an_int) {...}), that requests a constructor without parameter or where all parameters have default value, but you do not have that constructor, only a constructor requiring 2 int
Is there another way to do declare the class A object in class B without having to use a pointer to class A ?
you do not declare but define / instantiate a new instance of A each time you instantiate a new instance of B
Note you can create later the instance of A without using a pointer as with a_ptr having for instance
std::vector<A> a;
and when you know the instance of A you need doing for instance
a.push_back(A(an-int, an-int));
but the fact you want only one instance is not visible in the definition of a (out of a welcome comment)

C++:difference between assigning a value to an object and a class [duplicate]

This question already has answers here:
What is this weird colon-member (" : ") syntax in the constructor?
(14 answers)
Closed 4 years ago.
#include <iostream>
using namespace std;
class A{
public:
int a;
A() {a=0;}
A(int b) {a=b+1;}
};
class B{
public:
A a;
B():a(0) {}
};
int main(void) {
B *b = new B();
cout<<b->a.a<<endl;
return 0;
}
I replaced B():a(0) {} by B() {A(0)} and output changed from 1 to 0. I am wondering what's the difference between them?
B() : a(0) {} explicitly initializes the member B::a with the value 0. This is an example of a member initializer list. Basically, a(0) in this context calls a's constructor with the argument 0, which calls A::A(int), which, by your implementation, adds 1 to the argument and assigns the result to A::a. Thus in the first case, b->a.a == 1.
On the other hand, B() {A(0);} default-initializes B::a (because A has a default constructor) and creates a nameless local temporary object A(0); which is destroyed immediately without changing anything. It is functionally equivalent to B(){}, which is does nothing at all. You can omit this trivial constructor because the compiler can implicitly generate it for you. See special member functions for more information on how this works and under what conditions. Thus in the second case, you are calling the default constructor, which sets b->a.a == 0.

Why do you have to define an empty constructor c++ [duplicate]

This question already has answers here:
When do we need to have a default constructor?
(7 answers)
Closed 8 years ago.
I have the following classes:
class ArithmeticExpression
{
public:
ArithmeticExpression(std::string expr);
}
class Command
{
public:
Command(){};
//this is a virtual class
}
class CommandAssign : public Command
{
private:
ArithmeticExpression expr;
public:
CommandAssign();
CommandAssign(ArithmeticExpression);
}
Now when I try to write the constructor for the CommandAssign class as in:
CommandAssign::CommandAssign(ArithmeticExpression expr)
:Command()
{
this -> expr = ArithmeticExpression(expr.getExpr());
}
I get the error:
no matching function for call to ‘ArithmeticExpression::ArithmeticExpression()’
:Command()
Apparently I can fix that by adding an empty constructor in ArithmeticExpression class that does not do anything. What is it so special about this empty constructor that makes it work? I do not explicitly call anywhere. Do you always need to define an empty constructor in C++?
I wanted to emphasize that although from the title it seems that my question is similar to the one some users suggested as being a duplicate of, the answer I was looking for is NOT there. I was simply trying to understand what happens when a constructor is called and how to avoid defining a useless default constructor, which I knew already is not automatically defined by the compiler in the case where I define one with parameters.
A default constructor will only be automatically generated by the compiler if no other constructors are defined.
EDIT:
The default constructor is needed for object initialization.
All members are initialised before the constructor body begins. If one doesn't have an entry in the initialiser list, then it will be default-initialised; but this is only possible (for a class type) if it has a default constructor.
expr is not initialised in the initialiser list, and doesn't have a default constructor (since declaring any constructor prevents one from being implicitly generated), so it can't be initialised - hence the error.
You should initialise it in the list, rather than reassigning it in the constructor body:
CommandAssign::CommandAssign(ArithmeticExpression expr) :
expr(expr.getExpr())
{}
Note that there's no need to explicitly default-construct the Command sub-object. This also requires the constructor of ArithmeticExpression to be public: it's private in your example code.

C++ instantiate a class [duplicate]

This question already has answers here:
Why is there no call to the constructor? [duplicate]
(3 answers)
Most vexing parse
(1 answer)
Closed 9 years ago.
#include <iostream>
class Base
{
public:
int id;
};
int main()
{
Base b();
b.id = 1;
}
What is wrong with the object creation in the code above? What is the difference between Base b() and Base b?
This
Base b();
is parsed as a function declaration of a function called b() that returns a Base object. You need this:
Base b;
This will instantiate a Base object and call its default constructor. Note that this will not zero initialize base::id. You can fix this by providing a default constructor that does that:
class Base
{
public:
Base() : id(0) {}
int id;
};
and instantiate in the same way:
Base b;
The problem is that you are not instantiating an object, but rather declaring a function. This:
Base b(); // Function declaration! (not what you want)
Declares a function b() that returns an object of type Base and accepts no argument. Therefore, when you later try to access the member id, the compiler emits an error, because functions do not have members:
b.id = 1; // ERROR! b is a function, accessing member "id" makes no sense
If you want to create an instance of Base, instead, just remove the parentheses:
Base b; // Object instantiation! (what you want)
Notice that in C++11 you can use the uniform initialization syntax to create an instance of a class pretty much the way you were trying to do, but with curly braces instead of parentheses:
Base b{}; // Object instantiation! (what you want, in C++11)

Memberwise Initialization [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
C++ initialization lists
What is the difference between member-wise initialization and direct initialization in a class?
What is the difference between the two constructors defined in the class?
class A
{
public:
int x;
int y;
A(int a, int b) : x(a), y(b)
{}
A(int a, int b)
{
x = a;
y = b;
}
};
The theoretical answers have been given by other members.
Pragmatically, member-wise initialization is used in these cases :
You have a reference attribute (MyClass & mMyClass) in your class. You need to do a member-wise initialization, otherwise, it doesn't compile.
You have a constant attribute in you class (const MyClass mMyClass). You also need to do a member-wise initialization, otherwise, it doesn't compile.
You have an attribute with no default constructor in your class (MyClass mMyClass with no constructor MyClass::MyClass()). You also need to do a member-wise initialization, otherwise, it doesn't compile.
You have a monstruously large attribute object (MyClass mMyClass and sizeof(MyClass) = 1000000000). With member-wise initialization, you build it only once. With direct initialization in the constructor, it is built twice.
First one uses initialization and second one does NOT use initialization, it uses assignment. In the second one, the members x and y are default-initialized first (with zero), and then they're assigned with a and b respectively.
Also note that in the second one, members are default initialized only if the types of members are having non-trivial default constructor. Otherwise, there is no initialization (as #James noted in the comment).
Now see this topic to know:
What is a non-trivial constructor in C++?