Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the constructor called twice in C++?

Tags:

c++

templates

In this code the constructor is called twice.

How do I avoid that?

If I uncomment the default constructor code block then code does not give satisfactory output..

And I also want conditional based instantiation of template so I used void pointer.

#include<iostream.h>
template<class Type>
class Data{
      public:
      Type val;
      Data(Type v){
                cout<<"In Constructor Param";
                val = v;
      }
      Data(){
             //  cout<<"In Constructor Defa";  uncommnet this line
      }
      ~Data(){}
};
int main(){
    Data<void *> obj;
    obj = new Data<float>(31.34f);
    cout<<*(float*)obj.val;
}

Output:

In Constructor Param
In Constructor Param
31.34

Thanks for involving.

like image 593
Mahesh Meniya Avatar asked Mar 07 '12 15:03

Mahesh Meniya


2 Answers

The first call should be obvious: is in the call to new Data<float>(31.34f).

The second one is in a temporary object of type Data<void*> that is constructed in the next line. Your code is equivalent to the following:

Data<void *> obj;
Data<float> *t1 = new Data<float>(31.34f); //first!
void *t2 = t1;
Data<void *> t3(t2);  //second!
Data<void *> t4(t3); //copy constructor (elided)
obj = t4;  //operator=
cout<<*(float*)obj.val;

It is worth noting that the last line does a cast that is not probably what you want. That would be:

cout << ((Data<float*>)obj.val).val;

Or similar.

like image 59
rodrigo Avatar answered Oct 06 '22 02:10

rodrigo


The compiler implicitly declares a copy constructor for you. Next, your Data is implicitly convertible from Type, which in case of void* is implicitly convertible from any other pointer. Let's break this down:

Data<void*> obj;
Data<float>* new_obj = new Data<float>(31.34f); // your call to new
                       // the constructor is called the first time here
void* conv1 = new_obj; // implicit conversion to void*
Data<void*> conv2 = conv1; // implicit conversion from 'Type' (aka 'void*')
                           // the constructor is called the second time here
obj = conv2; // copy constructor

Also, the line cout<<*(float*)obj.val; is invoking undefined behaviour in C++98/03 (and your compiler seems to be much older than that), as your val actually is a Data<float>*, and not a float*. You should have that as

cout << static_cast<Data<float>*>(obj.val)->val;
like image 33
Xeo Avatar answered Oct 06 '22 01:10

Xeo