#include <iostream>
struct A
{
A(){std::cout<<"A()"<<std::endl;}
};
template<typename T>
struct B
{
A a;
T b;
B(){std::cout<<"B()"<<std::endl;}
};
int main()
{
B<B<B<int> > > Test;
return 0;
}
The odrer of calling constructors is
A()
A()
A()
B()
B()
B()
And i have no clue why is that. I thought it would be A B A B A B. Could you explain me why?
This is actually straight forward, if it was like A B A B A B, then you would have trouble if you wanted to access b from the constructor of B, since the order you thought implies that first member a gets instantiated, then ctor runs, then b gets initialized. In reality, every member is instantiated (constructed etc.) first, then, the constructors are called.
This is because member variables must be initialized before the body of the constructor is executed. Consider the following example:
struct A {
int value;
// Here we explicitly initialize 'value' with 5
A() : value(5) { }
};
struct B {
A a;
B()
{
// This is perfectly valid and would print 5,
// because 'a' has already been implicitly initialized
// with its default constructor.
std::cout << a.value;
}
};
If this weren't the case, what value would you expect a to have in B's constructor? You'd run into all sorts of issues. Therefore, the default constructor of A must be implicitly called before the body of B().
Essentially, to make it more explicit, this is what is happening:
// Initialize 'a' before body of constructor
B() : a()
{
std::cout << a.value;
}
First of all, let's analyze what you have here:
you have an object Test of class B<B<B<int> > >, which is:
class B<B<B<int> > > {
A a;
B<B<int> > b;
};
the second field of Test, Test.b is of class B<B<int> >, which is:
class B<B<int> > {
A a;
B<int> b;
};
then you have the second field of Test.b, Test.b.b, which is of class B<int>, which is:
class B<int> {
A a;
int b;
};
so the order of initialization is:
A() for Test.a.
A() for Test.b.a.
A() for Test.b.b.a.
no constructor as Test.b.b.b is of type int and has no constructor.
B<int>() for Test.b.b.
B<B<int> >() for Test.b.
B<B<B<int> > >() for Test.
Unfortunatelly, all the three constructors write on output the same thing: B(), but they're different constructors for different classes.
This is the expected behavior, because member initialization takes place before the body of the constructor. For realizing this, it is helpful to add the member initializers as well:
template<typename T>
struct B
{
A a;
T b;
B()
:
a(),
b()
{
std::cout<<"B()"<<std::endl;
}
};
To fully grasp the order of execution, let's add a dummy integer field.
I also added a template to display the nesting. See http://ideone.com/KylQQb for a demo.
#include <cstdio>
struct A
{
A()
:
dummy(printf("Starting to construct A()\n"))
{
printf("Fully constructed A()\n");
}
int dummy;
};
template <typename T>
struct Nesting;
template <>
struct Nesting<int>
{
constexpr static int value = 0;
};
template <template <typename> class T, typename I>
struct Nesting<T<I>>
{
constexpr static int value = 1 + Nesting<I>::value;
};
template<typename T>
struct B
{
int dummy;
A a;
T b;
B()
:
dummy(printf("Starting to construct B() with nesting %d\n", Nesting<B<T>>::value)),
a(),
b()
{
printf("Fully constructed B() with nesting %d\n", Nesting<B<T>>::value);
}
};
int main()
{
B<B<B<int>>> Test;
return 0;
}
The output of this will be
Starting to construct B() with nesting 3
Starting to construct A()
Fully constructed A()
Starting to construct B() with nesting 2
Starting to construct A()
Fully constructed A()
Starting to construct B() with nesting 1
Starting to construct A()
Fully constructed A()
Fully constructed B() with nesting 1
Fully constructed B() with nesting 2
Fully constructed B() with nesting 3
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
};
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.
I have class A and B.
B is a member of A.
I need to initialize B with other data members of A.
class A;
class B
{
public:
B(A& a){cout << "B constr is run \n";}
};
class A
{
public:
A(){}
void initB(A& a){b(a); cout << "A call init B \n"; }
private:
// other members ...
B b;
};
int main()
{
A a;
a.initB(a);
}
I got compile error:
classIns.cpp: In constructor âA::A()â:
classIns.cpp:14: error: no matching function for call to âB::B()â
classIns.cpp:8: note: candidates are: B::B(A&)
classIns.cpp:6: note: B::B(const B&)
classIns.cpp: In member function âvoid A::initB(A&)â:
classIns.cpp:16: error: no match for call to â(B) (A&)â
Why A(){} needs to call B::B() ?
How to initialize B with other data members of A ?
thanks
B has no default constructor, which means you have to initialise it in A's ctor.
struct A {
A() : b(*this) {}
private:
B b;
};
Any time you think of using init-like members, you're probably doing it wrong. Object should always be valid after the constructor is done.
You can use initialization chain in A constructor:
class B
{
public:
B(Type1 x, Type2 y)
{
}
void init(Type1 x, Type2 y) { ........}
};
class A
{
public:
A() : Amember1(), Amember2(), b(Amember1, Amember2) {}
private:
Type1 Amember1;
.....
B b;
};
But you can't invoke B constructor inside initB method because b is already constructed.
You can use a B::init() method with A data, like:
void A::initB(A& a){ b.init(a.Amember1, a.Amember2); cout << "A call init B \n"; }
Like this :
void initB(A& a){
b = B(a);
cout << "A call init B \n";
}
Off course, the class B needs a default constructor, and a copy constructor that takes reference to the object of type A.
Why A(){} needs to call B::B() ?
Because A has a data member B which needs to be initialized when you create an instance of the A class. In your case b is initialized with the default B c'tor.
Since you are specifying a constructor for B
public:
B(A& a){cout << "B constr is run \n";}
The default constructor :
B(){}
is not automatically generated by the compiler. So it complains.
Lets say I have the following code in what we expect to become the next C++ standard:
int f(int x)
{
std::cout << x;
return x * x;
}
struct A
{
A(int x) : m_x(x) {}
int m_x;
};
struct B : A
{
using A::A;
B() : m_y(f(m_x)) {}
int m_y;
};
int main()
{
B(5);
}
Would this call the default constructor of B and print out 5 and set m_y = 25? Or will the default constructor of B not run, and leave m_y uninitialized?
And if the latter, what is the rationale behind not calling the B default constructor? It is quite clear that the A(int) B inherits only initialises A, and leaves B in an indeterminate state. Why would C++ choose undefined behaviour over simply calling the default constructor of B()? It largely defeats the purpose of the inheriting constructors feature.
Edit:
Perhaps this should be allowed:
using A::A : m_y(...) { std::cout << "constructing..." << std::endl; ...; }
using A::A; implicitly declares B(int) in the derived class. That is it.
The rest of your program should not work as you expect. Because you're invoking B(int) with B(5), and that leaves m_y uninitialized.
See this example from Bjarne Stroustrup's site:
struct B1 {
B1(int) { }
};
struct D1 : B1 {
using B1::B1; // implicitly declares D1(int)
int x;
};
void test()
{
D1 d(6); // Oops: d.x is not initialized
D1 e; // error: D1 has no default constructor
}
http://www2.research.att.com/~bs/C++0xFAQ.html#inheriting
Another example from the same link:
struct D1 : B1 {
using B1::B1; // implicitly declares D1(int)
int x{0}; // note: x is initialized
};
void test()
{
D1 d(6); // d.x is zero
}
In C++ I have a reference to an object that wants to point back to its owner, but I can't set the pointer during the containing class' construction because its not done constructing. So I'm trying to do something like this:
class A {
public:
A() : b(this) {}
private:
B b;
};
class B {
public:
B(A* _a) : a(_a) {}
private:
A* a;
};
Is there a way to ensure B always gets initialized with an A* without A holding a pointer to B?
Thanks
Try this:
class A;
class B {
public:
B(A *_a) : a(_a) {};
private:
A* a;
};
class A {
public:
A() : b(this) {};
private:
B b;
};
Since B is contained completely in A, it must be declared first. It needs a pointer to A, so you have to forward-declare A before you declare B.
This code compiles under more-or-less current versions of g++.
In C++ I have a reference to an object that wants to point back to its owner, but I can't set the pointer during the containing class' construction because its not done constructing.
You can store the pointer alright.
What you can't do is to try to get to the members/methods of A through the pointer in the constructor of B, since the parent instance might not be fully initialized at the point:
#include <iostream>
class Y;
class X
{
Y* y;
public:
X(Y* y);
};
class Y
{
X x;
int n;
public:
Y(): x(this), n(42) {}
int get_n() const { return n; }
};
X::X(Y* p): y(p)
{
//Now this is illegal:
//as it is, the n member has not been initialized yet for parent
//and hence get_n will return garbage
std::cout << p->get_n() << '\n';
}
int main()
{
Y y;
}
If you were to switch around the members in Y, so n would get initialized first, the constructor of X would print 42, but that is too fragile to depend on.