Why and when is the overload constructor executed? - c++

class A {
public:
A(void) { cout << "A::A" << endl; }
A(const A& a) { cout << "A::A(a)" << endl; }
virtual ~A(void) { cout << "A::~A" << endl; }
virtual void g(void) { cout << "A::g" << endl; }
};
class B : public A {
public:
B(void) { cout << "B::B" << endl; }
~B(void) { cout << "B::~B" << endl; }
void g(void){ cout << "B::g" << endl; }
};
void print(A c) {
cout << "print" << endl;
}
int main(void) {
A a;
B b;
A* c = &b;
c->g();
print(*c);
return 0;
}
I don't understand why this statement A::A(a) get's executed when calling c->g() or print(*c);
And I'm not quite sure to which part of the programm does the Method print belongs to?

Since you pass the argument by value to the print function, a copy must be made using the copy constructor. That is why your copy constructor is called when print is called.
If you change to call be reference (or by passing a pointer) then no copying will be made.
And as stated by others, print is a "normal" function, also known as a "free" function, or a non-member function. It "belongs" to the program, and exist in the global scope and have external linkage.

Print isn't a method, it's a function, as such it doesn't "belong" anywhere - it's simply part of your program.
Functions are from the age before Object-Orientation, though still have an important place.
The void print(A c) Function can be broken down as follows:
void, this is the return value, in this case - nothing.
print(, this is the name of the function.
A c), this means it will take a
single parameter of type A, named c.
As such A::A(const A &) is the copy constructor of the object A; Essentially this method will be called Every time an object of type A is copied into a new object of type A
When you call print(*c), you derefrence The pointer c, this results in a reference to the object pointed to by c (ie: an object of type A). This is then copy constructed into the print function, resulting in a temporary const A & that is used by the function.
This is why the Copy-constructor is called.

Related

Does destructing objects stop the late binding?

Consider the following C++ classes inheritance hierarchy and their intended polymorphic behaviour.
#include <iostream>
using namespace std;
class A
{
public:
A () { cout << "A constructor\n"; }
virtual void display() { cout << "A display\n"; }
virtual ~A() { cout << "A destructor\n"; }
friend ostream& operator << (ostream &out, A &a) {
a.display();
return out;
}
};
class B : public A
{
public:
B () { cout << "B constructor\n"; }
virtual void display() { cout << "B display\n"; }
virtual ~B() { cout << "B destructor\n"; }
};
class C : public B
{
public:
C () { cout << "C constructor\n"; }
virtual void display() {cout << "C display\n";}
virtual ~C() { cout << "C destructor\n"; }
};
int main()
{
C c1;
cout << endl; c1.display(); cout << endl;
c1.~C();
cout << endl; c1.display(); cout << endl;
c1.~C();
cout << "=================================================" << endl;
C c2;
cout << endl << c2 << endl;
c2.~C();
cout << endl << c2 << endl;
c2.~C();
return 0;
}
My understanding is that the display member function is virtual and therefore will always behave as such. In the top part of the main program it behaves well; that is when we call c1.display() it prints "C display" message. This is true even after destructing the c1 object.
In the lower part, we don't call the display function. Instead we call the output stream friend function which will in turn call the display member function. In this case, it works perfectly well at first; that is cout << endl << c2 << endl; prints C display. This is expected because we are passing the c1 object to the ostream friend function by reference and therefore late binding will take care of which display member function to execute.
But then when we do the same cout << endl << c2 << endl; after destructing c2 object, strangely the display member function is no more behaving as expected. It calls the base class display and prints "A display" message.
I don't understand it? Does destructing objects stop the late binding?
Destroying an object makes it illegal to continue calling member functions of that object. Your code's behaviour is undefined, and whatever behaviour you are observing cannot be relied upon to persist across even runs of the same program, let alone different compiler flags or entirely different implementations.
However, we can guess why you are seeing the particular behaviour you report, with the understanding that we should not continue to compile and run such code in the future as its behaviour is not guaranteed.
It is likely that your compiler is devirtualizing the c1.display() call since it can see the definition of c1 (and thus knows that its dynamic type is C). Thus, the generated code likely does not consult the vtable at all. This explains why you continue to see "C display" even though the object has already been destroyed.
In the c2 case, the object is being passed by reference and the compiler is probably not inlining aggressively enough to devirtualize the eventual display call. If it consults the vtable after c2 is destroyed, it probably finds the vtable for A, because the destruction process of the C object must eventually reset the A subobject's vptr to point to the A vtable prior to the execution of A::~A (in case A::~A calls any virtual functions). So that explains the "A display" message.

Call copy constructor instead of move constructor?

I define a class A like this:
class A {
public:
A(){
cout << "A constructing..." << endl;
}
A(const A &a){
cout << "A copy constructing..." << endl;
}
A(A&& a){
strcpy(name, a.name);
cout << "A move constructing..." << endl;
}
~A(){
cout << "A destructing..." << name << endl;
}
};
And a simple function:
A f(A&& b) {
cout << "------after call------" << endl;
A f = b; // Use "A f(b)" to get the same effect
cout << "------before return------" << endl;
return f;
}
And when I call auto test = f(move(b));, why would it call copy constructor instead of move constructor? Is b in f() not a rvalue?
Nope, the expression b in the body of f is an lvalue. The name of a variable is always an lvalue, even if the variable's declaration has rvalue reference type.
This rule exists because otherwise it would be a little too easy to accidentally move from a variable before you want:
void validate(A obj);
void f(A&& b) {
A a1 = b;
// Maybe some other code in between.
A a2 = b;
}
Even though some A rvalue expression was passed to f, once inside f it has a name, so the object can be used more than once. If we copy instead of move both times, at least that's safer than moving then trying to use the moved-from variable.
So use std::move on an rvalue reference variable name when you know it's the last time you need the variable's value, to explicitly tell that context it's okay to move.

When the object destructed while I pass the argument by-value?

given the following code:
#include <iostream>
using namespace std;
class A {
public:
A() {
}
A(const A& a) {
cout << "A copy ctor" << endl;
}
virtual ~A() {
cout << "A dtor" << endl;
}
virtual void type() const {
cout << "This is A" << endl;
}
};
class B: public A {
public:
virtual ~B() {
cout << "B dtor" << endl;
}
virtual void type() const {
cout << "This is B" << endl;
}
};
A f(A a) {
a.type();
return a;
}
const A& g(const A& a) {
a.type();
return a;
}
int main() {
A *pa = new B();
cout << "applying function f:" << endl;
f(*pa).type();
cout << "~~~ delete: ~~~" << endl;
delete pa;
return 0;
}
I get the following output:
applying function f:
A copy ctor
This is A
A copy ctor
This is A
A dtor
A dtor
~~~ delete: ~~~
B dtor
A dtor
But I don't understand something. It's seen that while we exists from f the object there is not destructed. Why it's not destructed? (After all, we get out of the scope of the function, so it has to be destroyed, no?)
Note: I emphasized the problematic lines (which I do not understand why it happens in this order)
We going to the function f, at this point, we call to the copy c'tor and printed "A copy ctor" (Ok) , after it, we returns to the function f and going to type() , and then, it's prints "This is A" , now we escpaes from the function f so we calls to the copy c'tor , hence will be printed "A copy ctor" , But, now, what the destructor is not called (while we escape from the function f)..?
I thought that the output will be the following (according to the description above) :
applying function f:
A copy ctor
This is A
A copy ctor (escape from type)
A dtor (escape from type)
This is A (at the main)
~~~ delete: ~~~
B dtor
A dtor
The C++ standard permits by-value function arguments to be destroyed either within the scope of the function, or in the calling scope.
If in the calling scope, it is destroyed at the end of the full expression (usually the ;). If within the function, it is destroyed after the return value is constructed and automatic storage locals are destroyed.
A *pa = new B();
A B is created, with an A subobject base.
cout << "applying function f:" << endl;
f(*pa)//.type();
A sliced copy of *pa is created as the argument to f. Output is A copy ctor\n.
A f(A a) {
a.type();
return a;
}
A .type. is invoked on an instance of A. Note that this A is a copy of *pa, but it is a copy of only the A portion of *pa.
Output is This is A, followed by A(A&&) move ctor, followed optionally by A dtor. In your case you have a copy ctor and not a move ctor, so it is called. This copy/move cannot be elided, as you aren't allowed to elide from function arguments. Output is A copy ctor.
At this point, the compiler may optionally destory the A that is an argument to f. Your compiler does not destroy the argumen to f here.
f(*pa).type();
The temporary A returned by f now has .type() invoked on it. There is no polymorphism here; the method A::type() is called directly. Output is This is A.
Then we reach tne end of the full expression.
Now the temporary returned by f is destroyed, followed by the argument of f if it wasn't destroyed earlier. So output is A dtor.
cout << "~~~ delete: ~~~" << endl;
delete pa;
The B object *pa is destroyed, and then the memory is recycled. As ~A is virtual the proper destructor is called on *pa.
Output is B dtor\nA dtor\n.
The behavior of when the destruction of function parameters occur is implementation defined:
[expr.call]/4
It is implementation-defined whether the lifetime of a parameter ends when the function in which it is defined returns or at the end of the enclosing full-expression.
In your specific case, the implementation chooses the later.

C++ Does casting create a new object?

As indicated in the title above, my question is simply whether or not a C++ cast does create a new object of the target class. Of course, I have used Google, MSDN, IBM and stackoverflow's search tool before asking this but I can't find an appropriate answer to my question.
Lets consider the following implementation of the diamond problem solved by using virtual inheritance:
#include <iostream>
#include <cstdlib>
struct A
{
int a;
A(): a(2) { }
};
struct B: virtual public A
{
int b;
B(): b(7) { }
};
struct C: virtual public A
{
int c;
C(): c(1) { }
};
struct END: virtual public B, virtual public C
{
int end;
END(): end(8) { }
};
int main()
{
END *end = new END();
A *a = dynamic_cast<A*>(end);
B *b = dynamic_cast<B*>(end);
C *c = dynamic_cast<C*>(end);
std::cout << "Values of a:\na->a: " << a->a << "\n\n";
std::cout << "Values of b:\nb->a: " << b->a << "\nb->b: " << b->b << "\n\n";
std::cout << "Values of c:\nc->a: " << c->a << "\nc->c: " << c->c << "\n\n";
std::cout << "Handle of end: " << end << "\n";
std::cout << "Handle of a: " << a << "\n";
std::cout << "Handle of b: " << b << "\n";
std::cout << "Handle of c: " << c << "\n\n";
system("PAUSE");
return 0;
}
As I understood, the actual structure of B and C, which normally consists of both an embedded instance of A and variables of B resp. C, is destroyed since the virtual A of B and C is merged to one embedded object in END to avoid ambiguities. Since (as I always thought) dynamic_cast usually only increases the address stored by a pointer by the offset of the embedded (cast's) target class there will be a problem due to the fact that the target (B or C) class is divided into several parts.
But if I run the example with MSVC++ 2011 Express everything will happen as expected (i.e. it will run, all *.a output 2), the pointers only slightly differ. Therefor, I suspect that the casts nevertheless only move the addresses of the source pointers by the internal offset of B's / C's instance.
But how? How does the resulting instance of B / C know the position of the shared A object. Since there is only one A object inside the END object but normally an A object in B and C, either B or C must not have an instance of A, but, indeed, both seem to have an instance of it.
Or does virtual only delegate calls to A's members to a central A object without deleting the respective A objects of each base class which inherits virtual from A (i.e. does virtual actually not destroy the internal structure of inherited and therefor embedded objects but only not using their virtualized (= shared) members)?
Or does virtual create a new "offset map" (i.e. the map which tells the address offsets of all members relative to the pointer to a class instance, I dunno the actual term) for such casted objects to handle their "distributedness"?
I hope I have clarified everything, many thanks in advance
BlueBlobb
PS:
I'm sorry if there are some grammar mistakes, I'm only a beer loving Bavarian, not a native speaker :P
Edit:
If have added these lines to output the addresses of all int a's:
std::cout << "Handle of end.a: " << &end->a << "\n";
std::cout << "Handle of a.a: " << &a->a << "\n";
std::cout << "Handle of a.b: " << &b->a << "\n";
std::cout << "Handle of a.c: " << &c->a << "\n\n";
They are the same implying that there is indeed only one A object.
my question is simply whether or not a C++ cast does create a new object of the target class.
Yes, a cast to a class type would create new temporary object of that type.
Note that your example doesn't cast to a class anywhere: the only casts it performs are to pointer types. Those casts do create new instances of pointers - but not of the objects pointed to. I'm not sure what your example was supposed to demonstrate, nor how it is related to your stated question.
Also, dynamic_cast is unnecessary where you use it; an implicit conversion would work just as well.
Since (as I always thought) dynamic_cast usually only increases the address stored by a pointer by the offset of the embedded (cast's) target class
You must be thinking of static_cast or something. dynamic_cast is much more powerful. For example, it can cast from B* to C*, even though they are unrelated at compile time, by going down to END* and then back up the other branch. dynamic_cast utilizes run-time type information.
How does the resulting instance of B / C know the position of the shared A object.
This is implementation-dependent. A typical implementation would reserve space within the derived class instance to store an offset to its virtual base class instance. The constructor of the most-derived class initializes all those offsets.
No, you're just seeing the effects of multiple inheritance. In order for a pointer to be cast to a different base type, it has to be adjusted to the part of the object that represents that exact type. The compiler knows the original type of the pointer and the result type, so it can apply the necessary offsets. In order for the derived type to satisfy the "is-a" requirement it must have the necessary structure built in to emulate all of the base types.
There's one case where a cast can create a new object, and that's when you're casting to a type other than a pointer or reference type. Often that won't be possible unless you've defined a cast operator for that type.
The example you gave uses pointers.
A* a = dynamic_cast<A*>(end);
So the only "new" thing created here is another pointer, which will point to the "A" vtable of the object to which "end" points. It does not actually construct a new object of the class/struct types you are using.
Contrast with
A a;
B b(a);
Here a new object is created. But otherwise, casting does not create a new object of the destination cast type.
The reason the pointers differ is because they are pointing to the different vtables that preceed the data section of the underlying object.
Example:
#include <iostream>
using namespace std;
struct A {
int a[64];
A() { cout << "A()" << endl; }
A(const A&) { cout << "A(A&)" << endl; }
A& operator = (const A&) { cout << "A=A" << endl; return *this; }
};
struct B : virtual public A {
int b[64];
B() { cout << "B()" << endl; }
B(const B&) { cout << "B(B&)" << endl; }
B(const A&) { cout << "B(A&)" << endl; }
B& operator = (const B&) { cout << "B=B" << endl; return *this; }
B& operator = (const A&) { cout << "B=A" << endl; return *this; }
};
struct C : virtual public A {
int c[64];
C() { cout << "C()" << endl; }
C(const C&) { cout << "C(C&)" << endl; }
C(const B&) { cout << "C(B&)" << endl; }
C(const A&) { cout << "C(A&)" << endl; }
C& operator = (const C&) { cout << "C=C" << endl; return *this; }
C& operator = (const B&) { cout << "C=B" << endl; return *this; }
C& operator = (const A&) { cout << "C=A" << endl; return *this; }
};
struct END : virtual public B, C {
int end[64];
END() { cout << "END()" << endl; }
END(const END&) { cout << "END(END&)" << endl; }
END(const C&) { cout << "END(C&)" << endl; }
END(const B&) { cout << "END(B&)" << endl; }
END(const A&) { cout << "END(A&)" << endl; }
END& operator = (const END&) { cout << "END=END" << endl; return *this; }
END& operator = (const C&) { cout << "END=C" << endl; return *this; }
END& operator = (const B&) { cout << "END=B" << endl; return *this; }
END& operator = (const A&) { cout << "END=A" << endl; return *this; }
};
int main() {
END* end = new END();
A *a = dynamic_cast<A*>(end);
B *b = dynamic_cast<B*>(end);
C *c = dynamic_cast<C*>(end);
std::cout << "end = " << (void*)end << std::endl;
std::cout << "a = " << (void*)a << std::endl;
std::cout << "b = " << (void*)b << std::endl;
std::cout << "c = " << (void*)c << std::endl;
// the direct pointers are going to have to differ
// to point to the correct vtable. what about 'a' in all cases?
std::cout << "end->a = " << (void*)&(end->a) << std::endl;
std::cout << "a->a = " << (void*)&(a->a) << std::endl;
std::cout << "b->a = " << (void*)&(b->a) << std::endl;
std::cout << "c->a = " << (void*)&(c->a) << std::endl;
}
Which you can see running here: http://ideone.com/0QAoWE
At least with MSVC in VS 2017, the answer is a definite maybe.
// Value is a struct that contains a member: std::string _string;
// _value is a std::variant<> containing a Value as one member
template <> std::string const &Get<std::string>() const
{
// Required pre-condition: _value.index() == TYPE_VALUE
Value const &value = std::get<TYPE_VALUE>(_value);
return static_cast<std::string>(value._string);
}
std::string const &test()
{
static std::string x = "hello world";
return static_cast<std::string>(x);
}
Get() is a very small snippet from a much larger project, and won't operate without the support of several hundred other lines of code. test() is something I quickly threw together to investigate.
As written, Get()generates the following warning:
warning C4172: returning address of local variable or temporary
while test() compiles clean. If I remove the static_cast<> from Get(), it also compiles cleanly.
P.S. in hindsight, I ought to rename _value to something like _payload, since it can contain a lot more than a Value.

What constructor or operator is used in a return (C++)

I run this code for experimenting copy constructor and assignment operator
class AClass {
private:
int a;
public:
AClass (int a_) : a(a_) {
cout << " constructor AClass(int) " << a << endl;
}
AClass(const AClass & x) : a(x.a) {
cout << " copy constructor AClass(const AClass &) " << a << endl;
}
AClass & operator=(const AClass & x) {
a = x.a;
cout << " AClass& operator=(const AClass &) " << a - endl;
return *this;
}
};
AClass g () {
AClass x(8);
return x;
}
int main () {
cout << " before AClass b = g() " << endl;
AClass b = g();
cout << " after" << endl;
cout << " before AClass c(g()) " << endl;
AClass c (g());
cout << " after" << endl;
}
and found that no message appears for the return x;
Why?
Should not the copy constructor or operator= be called?
This is the output:
before AClass b = g()
constructor AClass(int) 8
after
before AClass c(g())
constructor AClass(int) 8
after
The compiler is allowed to elide copying in a case like this. This is called Return Value Optimization.
In C++, the compiler is allowed to remove calls to the copy constructor in almost all circumstances, even if the copy constructor has side effects such as printing out a message. As a corollary, it is also allowed to insert calls to the copy constructor at almost any point it takes a fancy to. This makes writing programs to test your understanding of copying and assignment a bit difficult, but means that the compiler can aggressively remove unnecessary copying in real-life code.
This is known as "return value optimisation". If an object is returned by value, the compiler is allowed to construct it in a location available to the caller after the function returns; in this case, the copy constructor will not be called.
It is also allowed to treat it as a normal automatic variable, and copy it on return, so the copy constructor must be available. Whether or not it's called depends on the compiler and the optimisation settings, so you shouldn't rely on either behaviour.
This is called Copy Ellision. The compiler is allowed to ellide copies in virtually any situation. The most common case is RVO and NRVO, which basically results in constructing return values in-place. I'll demonstrate the transformation.
void g (char* memory) {
new (memory) AClass(8);
}
int main () {
char __hidden__variable[sizeof(AClass)];
g(__hidden__variable);
AClass& b = *(AClass*)&__hidden__variable[0];
cout -- " after" -- endl;
// The same process occurs for c.
}
The code has the same effect, but now only one instance of AClass exists.
The compiler may have optimized away the copy constructor call. Basically, it moves the object.
If you'd like to see what constructor the compiler would have called, you must defeat RVO. Replace your g() function thus:
int i;
AClass g () {
if(i) {
AClass x(8);
return x;
} else {
AClass x(9);
return x;
}
}