I wrote this small program to test my understanding. What I'm having trouble understanding is that constructors aren't inherited, but class B is able to call the constructor of class A!
#include <iostream>
using namespace std;
class A {
public:
A(int x = 2) { //Constructor A
num = x;
}
int getNum() {
return num;
}
protected:
int num;
};
class B: public A { //Constructor B
public:
B() {
A(5);
}
};
int main() {
A a(3); //create obj a with num = 3
B b; //create obj b
cout << a.getNum() << endl;
cout << b.getNum() << endl;
return 0;
}
The output is:
3
2
What did the constructor A's call do exactly? It didn't use the passed argument to initialize object b's number!
Furthermore, if I remove the default value from class A's constructor, I get compilation error:
no matching function for call to 'A::A()'
So what's exactly happening here?
I know that the correct way is to do so:
class B: public A { //Constructor B
public:
B() : A(5) {
}
};
Which gives the output:
3
5
But this is just for the purpose of understanding.
Lets take a look at the B constructor:
B() {
A(5);
}
Here you actually "call" the A constructor twice. Once as part of the B construction (where the "default" A constructor is called), and once as you create a temporary object inside the B constructor body.
The sequence is as
B constructor called
A default constructor called as part of the initialization of the B object
The body of the B constructor is entered
A non-default constructor called (with argument 5) as part of creation of the temporary object
The temporary object goes out of scope and is destructed
The body of the B constructor exits
Related
If I create derived object it calls base constructor first and then derived constructor. Does it mean that parent object also get created when we create derive object?
I don't think parent object gets created, but why does the parent constructor get called?
#include<iostream>
using namespace std;
class A {
public : A(){
cout<<"inside A constructor"<<endl;
}
};
class B : public A{
public : B(){
cout << "inside B constructor" << endl;
}
};
int main() {
B b;
return 0;
}
Output:
inside A constructor
inside B constructor
I don't think parent object get created [...]
You are wrong.
B constists of a A subobject and any members that B has in addition. Consider this example:
struct A {
int a = 0;
};
struct B : A {
B() {}
};
int main() {
B b;
b.a = 42;
}
B inherits the members from A. Those members do not come out of nowhere, but they are part of Bs subobject of type A and that has to be constructed. When you do not call a constructor explicitly then it will be default constructed. The above is roughly equivalent to:
struct A {
int a = 0;
};
struct B : A {
B() : A() {}
// ^^^ call default constructor of A
};
Given that I have:
a base class called A
a constructor for A that takes an int argument
a subclass called B that inherits from A
a member variable of class B that is an int and is called A
How do I call the constructor A::A(int) in B's constructor? It seems that all I can do is initialize the member variable called A.
Her's a short code reproducing the issue:
#include <iostream>
class A
{
public:
A();
A(int);
};
class B : public A
{
public:
B();
int A = 100;
};
A::A()
{
std::cout << "in constructor A";
}
A::A(int s)
{
std::cout << "value in A constructor " << s;
}
// Here I want to initialize the base class with 50
// and the member with 78. Is it possible?
B::B() : A(50), A(78)
{
std::cout << "in Constructor B";
std::cout << A;
}
int main()
{
B b;
}
I want to initialize class member A with 78, and call the base class constructor with 50. How can I do that?
If I try to assign to the member instead:
B::B() : A(50)
{
A = 78;
std::cout << "in Constructor B";
std::cout << A;
}
the output is
in constructor Ain Constructor B78
It's not calling the A::A(int) overloaded constructor.
I am trying to do an assignment in my book but I do not understand the output. When the main code in the program is run the output is:
B::B(3)
B::B() //why is this outputted
B::B(-3)
D::D(3)
It gets this from calling B::B(int n) {} first and then B::B() {} followed by the the next two lines which I get. So the program called the first one since it is declared as the constructor the class A in the function and it has to assign values, what I dont get is output line 2, why is B::B() {} even called? it gets called as a constructor but shouldnt just the constructor with parameters get called?
class B {
public:
B(); //why is this called?
B(int n);
};
// Definitions of B
B::B() {
cout << "B::B()\n";
}
B::B(int n) {
cout << "B::B(" << n << ")\n";
}
class D : public B {
public:
D();
D(int n);
private:
B b;
};
// Definitions of D
D::D() {
cout << "D::D()\n";
}
D::D(int n) : B(n) {
b = B(-n);
cout << "D::D("<< n <<")\n";
}
int main(int argc, const char * argv[]) {
// insert code here...
D d(3);
return 0;
}
First the base class constructor is called: B::B(3).
Then the constructor for the b field is called: B::B().
Then the derived constructor body is executed (after all fields are constructed).
D's constructor first constructs another B on the line b = B(-n); (so B::B(-3) is printed), then prints D::D(3).
Your class D contains two objects of type B.
the implicit B from inheritance
the explicit B member named b
You could rewrite the constructor
D::D(int n) : B(n)
{
b = B(-n);
cout << "D::D("<< n <<")\n";
}
like
D::D(int n) : B(n), b()
{
b = B(-n);
cout << "D::D("<< n <<")\n";
}
where it is apparent where the B::B() comes from. Thus your output is easily explained:
B::B(3) // base constructor of `D`
B::B() // default construction of `b` member
B::B(-3) // explicit construction inside D::D(int)
D::D(3) // D::D(int)
If you write
D::D(int n) : B(n), b(-n)
{
cout << "D::D("<< n <<")\n";
}
instead, there is only
B::B(3)
B::B(-3)
D::D(3)
left.
Addressing the comment:
Imagine D to look like:
class D : public B
{
public:
D(int);
};
with the constructor definition
D::D(int v) { std::cout << "foo with " << v; }
then, the code
D d(3);
prints
B::B()
foo with 3
and it is perfectly valid as long as B is default constructible.
If B would lack a default constructor you'd get a compiler error and you'd want to rewrite the definition of D to
D::D(int v) : B(3) { std::cout << "foo with " << v; }
Every direct base class or member that is not part of the constructors initializer list is default constructed (in case of a class type) or left uninitialized in case of a fundamental type.
Confusion in constructor calling via temporary object as argument in a function
#include <iostream>
using namespace std;
class Base
{
protected:
int i;
public:
Base() {
cout<<"\n Default constructor of Base \n";
}
Base(int a)
{
i = a;
cout<<"Base constructor \n";
}
void display(){
cout << "\nI am Base class object, i = " << i ;
}
~Base(){
cout<<"\nDestructor of Base\n";
}
};
class Derived : public Base
{
int j;
public:
Derived(int a, int b) : Base(a) {
j = b;
cout<<"Derived constructor\n";
}
void display() {
cout << "\nI am Derived class object, i = "<< i << ", j = " << j;
}
~Derived(){
cout<<"\nDestructor Of Derived \n";
}
};
void somefunc (Base obj) //Why there is no call to default constructor of Base class
{
obj.display();
}
int main()
{
Base b(33);
Derived d(45, 54);
somefunc( b) ;
somefunc(d); // Object Slicing, the member j of d is sliced off
return 0;
}
My question is that why there is no call to Default Constructor of Base Class,when we are creating a Temporary object of a Base class in function ( void somefunc(Base obj) )
My question is that why there is no call to Default Constructor of Base Class,when we are creating a Temporary object of a Base class in function
An instance of Base is constructed using the copy constructor when the call to somefunc is made. That object is not constructed using the default constructor. A default copy constructor is created by the compiler since you haven't defined one.
It's not a temporary object. The argument is passed by value to the function, so the copy ctor will be called, not default ctor. Note that compiler will provide a copy constructor if there is no user defined, you can define it by yourself to output some debug info.
Base(const Base& a) : i (a.i)
{
cout<<"Base copy constructor \n";
}
it will call copy construct function to create the Temporary object of a Base class in function
When a constructor in a superclass receives arguments, it is no longer a default constructor, right? For example
class a {
public:
int a;
int b;
a(int c, int d){
cout<<"hello";
};
}
Now when I try to make a subclass, the program causes an error, it says "no default constructor is defined in the super class". How can I solve this problem? I know that if I remove the arguments, everything is going to be fine but I'm told not to do so in my C++ test. Please help me figure it out.
If your base class isn't default-constructible, or if you don't want to use the base class's default constructor, then you simply have to tell the derived class how to construct the base subobject:
struct b : a
{
b(int n) : a(n, 2*n) { }
// ^^^^^^^^^ <-- base class initializer, calls desired constructor
};
You normally deal with this with an initializer list:
#include <iostream>
class a {
public:
a(int c, int d) { std::cout << c << " " << d << "\n"; }
};
class b : public a {
public:
b() : a(1, 2) {}
};
int main() {
b x;
return 0;
}
You have to provide a constructor which takes no argument yourself.
a::a()
{
}
Once you provide any constructor for your class the compiler does not generate the implicit default constructor which takes no arguments. So if your code then needs a no arguments constructor you will have to provide it yourself.