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
}
Related
#include<iostream>
class A {
int a, b;
public:
void setdata(int x, int y) { a = x; b = y; }
void showdata() { std::cout << a << b; }
};
class B : public A { };
int main() {
A a1;
B b1;
a1.setdata(5, 4);
a1.showdata();
b1.showdata();
}
I just want to print the values of the a and b members using the b1 object of class B, as it can access the member functions of class A since class B has public inheritance of class A. But, I am getting garbage values when I try to print the values of a and b using b1.
Can someone explain why this is happening and how to fix it?
a1 and b1 are completely separate object instances in memory. They have their own copies of the a and b members in memory. They have nothing to do with each other at all. Whatever you do to a1 does not affect b1 at all, and vice versa.
You are initializing the members of a1 only, you are not initializing the members of b1 at all. That is why you are seeing garbage when you try to print out the members of b1.
Before calling b1.showdata(), you need to call b1.setdata() to initialize b1's members, eg:
int main() {
A a1;
B b1;
a1.setdata(5, 4);
a1.showdata();
b1.setdata(1, 2); // <-- add this!
b1.showdata();
}
You should also give class A a default constructor that initializes the members to default values, in case setdata() is not called after construction (such as what happened in your case), eg:
class A {
int a, b;
public:
A() : a(0), b(0) {} // <-- add this!
void setdata(int x, int y) { a = x; b = y; }
void showdata() { std::cout << a << b; }
};
Alternatively, you might consider giving class A and class B a constructor that takes values as input, eg:
class A {
int a, b;
public:
A() : a(0), b(0) {}
A(int x, int y) : a(x), b(y) {} // <-- add this!
void setdata(int x, int y) { a = x; b = y; }
void showdata() { std::cout << a << b; }
};
class B : public A {
public:
B() : A() {}
B(int x, int y) : A(x, y) {}
};
/* or simpler:
class B : public A {
public:
using A::A; // <-- inherit all constructors
};
*/
int main() {
A a1(5, 4);
B b1(1, 2);
a1.showdata();
b1.showdata();
}
#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
I'm just supposed to be getting used to basic copy constructors.
I assumed I properly placed copy constructors.
But when I try to compile, I keep getting the error "No matching constructor for initialization of B"
I'm a bit confused.
class A {
int valuea;
public:
A(const A&); // copy constructor
int getValuea() const { return valuea; }
void setValuea(int x) { valuea = x; }
};
class B : public A {
int valueb;
public:
B(int valueb);
B(const B&); // copy constructor
int getValueb() const { return valueb; }
void setValueb(int x) { valueb = x; }
};
int main () {
B b1;
b1.setValuea(5);
b1.setValueb(10);
B b2(b1);
cout << "b2.valuea=" << b2.getValuea() << "b2.valueb=" << b2.getValueb() << endl;
return 0;
}
By declaring B(int) and B(const B &), you have disabled the default constructor that is implicitly placed in the class for you when you have no other constructors because for all the compiler knows, you might not want a default constructor, so it can't make assumptions (see here).
Add the following to B, remembering to initialize the base and members with it:
B(){}
In C++11, this works well:
B() = default;
That will allow B to have a default constructor for use when you declare B b1;
The same thing goes for A, too. You have a copy constructor, so there's no longer any default constructor implicitly placed in for you.
class A
{
public: int a,b,c;
};
class B: public A
{
public: int d;
B():d(0){} // Some hackery needed here
};
int main()
{
B obj;
std::cout<< obj.a << std::endl; // garbage
std::cout<< obj.b << std::endl; // garbage
std::cout<< obj.c << std::endl; // garbage
std::cout<< obj.d << std::endl; // 0
}
How could the subobject data members a,b and c be initialized to 0? I am not permitted to modify class A.
Try
B() : A() , d(0){}
A() value initializes A and since A is a POD the members will be default(zero) initialized
I tested this as I thought it might work (even without Prasoon's answer)
B::B() : A(), d(0)
{
}
might work, because you are then "initialising" A.
It didn't, by the way. Output:
1,32,123595988
This would work though:
// put this in B.cpp anonymous namespace
const A a_init = { 0, 0 ,0 };
followed by:
B::B() : A( a_init), d(0)
{
}
I am testing using g++ 4.3.2. Now THIS worked:
B::B() : A(A()), d(0)
{
}
Perhaps I'm missing something, but how about this?
class B: public A
{
public: int d;
B():d(0){a=b=c=0;}
}
The proper way is of course to have A's constructor initialize it's members. Otherwise, as the members are not private, you can assign them values from inside the B constructor.
a = 0;
etc, actually works.
declare the derived class constructor as shown below
class B: public A
{
public: int d;
B():a(0),b(0),c(0),d(0)
{
}
};
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.