So I'm just getting caught up in some nuisances of C++. Specifically, passing anonymous variables by reference for use in an initializer list for a class in C++. Consider the following code;
class A {
public:
int x;
A(int x=0) : x(x) {
std::cout <<"A: creatred\n";
}
~A() {
std::cout << "A: destroyed\n";
}
};
class B {
public:
A a;
B(const A& in) : a(in) {
std::cout <<"B: creatred\n";
}
~B() {
std::cout << "B: destroyed\n";
}
};
int main() {
B b(A(0));
std::cout << "END\n";
return 0;
}
outputs:
A: creatred
B: creatred
A: destroyed
END
B: destroyed
A: destroyed
I count 2 creations and 3 destructions. What's going on? Way I see it, I'm using an anonymous variable A(0) as input when creating b. Not sure what the order of things are now. A reference to the anonymous variable is created and used to copy (the copy constructor will be called in the initializer list, yes?) the member variable a. When is the anonymous variable destroyed? And in general, why am I seeing 2 constructors called and 3 destructors. Thanks.
You didn't override A's copy constructor to print a message...
Specifically, a(in) invokes it.
The missing constructor would be the copy constructor for A.
You copy construct A in the below line.
B(const A& in) : a(in)
A: destroyed
END
This is the temporary being destroyed, it is destroyed at the end of the line
B b(A(0));
Related
For certain reasons, I want to have multiple instances of class A all have access to a single instance of class B. B has public member functions that allow objects of A to get data from B, but not to change it. I'm trying to do this by declaring an object of B in my main function, then passing it to the constructor when I declare objects of type A.
void main () {
B obj_b;
A A1(obj_b);
A A2(obj_b);
A A3(obj_b);
cout << A1.getfoo() << endl;
cout << A2.getfoo() << endl;
count << A3.getfoo() << endl;
}
class B{
private:
int foo = 9;
public:
int getfoo(){return foo;}
};
class A {
private:
B *bptr;
public:
A(B b){ this->bptr = &b; }
int getfoo(){ return bptr->getfoo(); }
};
This compiles and runs, but I get very weird results. The return values from getfoo are sometimes correct sometimes incorrect. Am I handling the pointers incorrectly? Is there a better way to do this?
In the A constructor, the argument b is a local variable, its life-time ends when the constructor function ends. You can't save a pointer to it, that pointer will become invalid immediately.
Either use smart pointers, or use a reference and constructor initializer lists:
class A
{
public:
// Pass by reference
A(B& b)
: b{ b } // Initialize the member variable b with the argument b
{
// Empty body
}
private:
B& b; // Reference to a B object
};
I was pretty sure the calling of B(A()) will call the defined constructor of B in my code.
But I was surprised to find out that it didn't call to my constructor B and of course didn't print "Constructor B".
So, to which constructor this code is calling (what is the signature of this constructor that it's calling to)?
struct A
{
};
struct B
{
B(const A a) { std::cout << "Constructor B" << std::endl; }
};
int main()
{
B(A());
return 0;
}
It doesn't construct an object with type B as you expected, then no constructor is called.
When declaring variables we can add (unnecessary) parentheses around the variable name, i.e. int (a); has the same effect as int a;. Similarly, B(A()); is same as B A();, which declares a function named A, which takes no parameters and returns B.
As the workaround you can change () to {}, e.g.
B(A{});
B{A()};
B{A{}};
LIVE
Consider the following code
#include <iostream>
using namespace std;
class A
{
int x;
public:
A() { cout << "A's constructor called " << endl; }
};
class B
{
public:
static A a;
B() { cout << "B's constructor called " << endl; }
static A getA() { return a; }
};
A B::a; // definition of a
int main()
{
B b1, b2, b3;
A a = b1.getA();
cout<<&a<<endl;
cout<<&B::a;
return 0;
}
the output is
A's constructor called
B's constructor called
B's constructor called
B's constructor called
0x7fff03081280
0x601194
Now lets consider another similar code
#include <iostream>
using namespace std;
class A
{
int x;
public:
A() { cout << "A's constructor called " << endl; }
};
class B
{
public:
static A a;
B() { cout << "B's constructor called " << endl; }
static A getA() { return a; }
};
A B::a; // definition of a
int main()
{
B b1, b2, b3;
A a ;
a= b1.getA();
cout<<&a<<endl;
cout<<&B::a;
return 0;
}
the output is
A's constructor called
B's constructor called
B's constructor called
B's constructor called
A's constructor called
0x7ffc485a1070
0x601194
Now my question is that why in the first case the constructor of A is called only once , whereas in the second code its called twice.
Also the two output &a and &B::a are different so it means they are two different objects .
Please explain why this is so.
In your first code
A a = b1.getA();
the copy-constructor of A gets called which doesn't generate any output. Define it yourself and you'll get a similar output to your second code.
Hmm, B::a is B's (public) static member instance of otherwise quite an usual class A. So, the first A's constructor logged is that of B::a, which should be initialized before control enters main, but next you create a separate instance of A local to main, it is constructed in order alongside with other main's local variables (here, right after all the Bs) and it is naturally distinct from B::a.
Now my question is that why in the first case the constructor of A is called only once , whereas in the second code its called twice.
Because in the first case you default-initialised only the static B::a, and copy-initialised the local a.
In the second you default-initialised both objects.
The crucial difference is that you only print a message in the default constructor, and don't print anything in the copy constructor.
Also the two output &a and &B::a are different so it means they are two different objects .
That is correct. a is a local variable, while B::a is a static member variable. They are different objects.
Static member variables of class type represent a storage with process-wide life span. It gets initialized as such, at some point before entry point to program - the beginning of main() - is reached. That's the first constructor call.
The line
A a = b1.getA();
initializes object a by calling copy constructor and through return value optimization and copy elision there is no default constructor call.
The second variant:
A a; // A() call
a = b1.getA(); // operator= call
Modified class
class A
{
int x;
public:
A(const A& a): x(a.x) { cout << "A's copy constructor called " << endl; }
A(A&& a): x(a.x) { a.x = 0; cout << "A's move constructor called " << endl; }
const A& operator=(const A& a) { x = a.x; cout << "A's copy operator= called " << endl; }
A() { cout << "A's constructor called " << endl; }
};
would give this output in first case:
A's constructor called
B's constructor called
B's constructor called
B's constructor called
A's copy constructor called
And second case would result in:
A's constructor called
B's constructor called
B's constructor called
B's constructor called
A's constructor called
A's copy constructor called
A's copy operator= called
It is simple to understand that whenever the class instance (object) getting created associated constructor is getting called.
Now my question is that why in the first case the constructor of A is called only once , whereas in the second code its called twice.
You are creating second object directly in stack and constructor is getting called in later case, first one is the static and second one by creating object in stack by below statement.
A a ;
In first case, instead of constructor, copy constructor is getting called so thats why you are not getting the print statement second time.
A a = b1.getA();
I have always thought that base class constructors/destructors/friends are not inherited by derived class. This link confirms this :
http://www.geeksforgeeks.org/g-fact-4/.
I was also aware that we can write base class constructors in the initialization list of derived class initializer list.
Having said that: I tried to check my skills today about it. But I failed to guess the output of this program.
#include<iostream>
class A {
int x, y;
public:
A(int a = 0, int b = 0) : x(a), y(b) {
std::cout << "A ctor called" << std::endl;
}
void print_A() {
std::cout << "x = " << x << std::endl;
std::cout << "y = " << y << std::endl;
}
};
class B : public A {
int z;
public:
// I knew that A member can be initilized like this.
B(int a = 0, int b = 0, int c = 0) : z(a), A(b, c) {
std::cout << "C ctor called" << std::endl;
// I was not aware about that.
A(b, c);
}
void print_B() {
std::cout << "z = " << z << std::endl;
}
};
int main() {
B b(1, 2, 3);
b.print_A();
b.print_B();
}
Output :
A ctor called
C ctor called
A ctor called
x = 2
y = 3
z = 1
Couple of questions:
If constructors/desctructors/friends are not inherited from base, how can class 'B' is able to access constructor of class 'A' here.
How come you get this output? How come two constructors of 'A' have been called.
Your understanding is faulty. This:
// I was not aware about that.
A(b, c);
doesnt initialise the A member of B, it (notionally at least) creates a temporary, nameless local variable in the body of the constructor, somewhat analogous to if you had said:
A a(b, c);
The constructor for A is a public member, so anything can call it.
If constructors/desctructors/friends are not inherited from base, how can class 'B' is able to access constructor of class 'A' here?
"Not inherited" does not mean "inaccessible to the derived class". A derived class can certainly reference a base constructor. B's constructor does it twice:
The first access is in the initialization list
The second access is in the body of B's constructor; it creates a temporary object
Inheriting a constructor would mean that users of B would be able to access B(int, int), which they cannot do*.
It seems like a constructor call. Why does it create a temporary object?
Consider this method:
void foo(const A& a);
A common way is to call it like this:
A a(1, 2);
foo(a);
but C++ also lets you call it without creating A on a separate line:
foo(A(1, 2));
In this case C++ creates a temporary object, and passes foo a reference to it. When you write
A(1, 2)
C++ also creates a temporary object for you by calling its constructor.
How come two constructors of 'A' have been called.
The constructor is invoked twice; that is why you get the output.
* C++11's using mechanism allows you to achieve an effect very similar to constructor inheritance, provided that you follow specific rules.
the constructor is called by the every time A(b, c) is called;
you are calling it on line
B(int a = 0, int b = 0, int c = 0) : z(a), A(b, c) {
and you are calling it inside the b constructor
// I was not aware about that.
A(b, c);
the code works as intended
If constructors/desctructors/friends are not inherited from base, how can class 'B' is able to access constructor of class 'A' here.
You mean on these lines?
// I was not aware about that.
A(b, c);
It isn't "accessing the constructor" in the sense you think. It just creates (and immediately discards) an anonymous temporary A in the body of the constructor function.
How come you get this output? How come two constructors of 'A' have been called.
Because you created two instances of A: the base-class subobject of B b, and the anonymous temporary.
Here's an easy experiment to verify this, with the following logging:
// in A
A(int a = 0, int b = 0) : x(a), y(b) {
std::cout << "A::A #" << static_cast<void*>(this) << std::endl;
}
~A() {
std::cout << "A::~A #" << static_cast<void*>(this) << std::endl;
}
// in B
B(int a = 0, int b = 0, int c = 0) : z(a), A(b, c) {
std::cout << "B::B #" << static_cast<void*>(this) << std::endl;
A(b, c);
}
~B() {
std::cout << "B::~B #" << static_cast<void*>(this) << std::endl;
}
I get output something like
A::A #0xffec7054
B::B #0xffec7054
A::A #0xffec704c
A::~A #0xffec704c
x = 2
y = 3
z = 1
B::~B #0xffec7054
A::~A #0xffec7054
See that the instance address of the second A::A is different from the first (so it's a different object), and it's followed by an A::~A (because the anonymous temporary goes immediately out of scope).
Notes:
If you could "call the constructor" as you suggested originally, it would look something like
auto subobject = static_cast<A*>(this);
new (subobject) A(b, c);
and would be very wrong. The A subobject of b was completely constructed when it's own constructor completed, before the body of B's constructor starts. You can't just re-create a new object in the same space, what would happen to the old one?
This may seem trivial, but for objects with dynamically-allocated resources, it would be a serious bug. It's not allowed.
You wrote your initializer list : z(a), A(b, c), but should be aware the base-class subobject will be constructed before the derived-class members are initialized. That is, those two things will happen in the opposite order to what you wrote. It's not (necessarily) an error, but it's worth knowing.
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.