Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Explicit Call to a Constructor

I know the concept that we can call the Constructor both Explicitly and Implicitly, and i have tested both the scenarios(generally till now my all purposes got fulfilled by calling constructor Implicitly), but i was wondering that constructor get called implicitly whenever we create objects, so what is the main reason behind calling the constructor Explicitly. What advantage or disadvantage it provides when we call constructor Explicitly over the Implicit Call?

Example

class integer
{
   int m ,n;
 public:
   integer (int x , int y); 
};
integer :: integer (int x , int y )
{
   m=x; n = y;
}

Now if i call like

integer int1 = integer( 0 , 100); //  Explicit Call
integer int1(1,100); // implicit call
like image 688
Tejendra Avatar asked Aug 20 '12 10:08

Tejendra


People also ask

What is explicit constructor invocation?

From within a constructor, you can also use the this keyword to call another constructor in the same class. Doing so is called an explicit constructor invocation. Here's another Rectangle class, with a different implementation from the one in the Objects section.

What is the implicit constructor?

implicit constructor is a term commonly used to talk about two different concepts in the language, the. implicitly declared constructor which is a default or copy constructor that will be declared for all user classes if no user defined constructor is provided (default) or no copy constructor is provided (copy).


3 Answers

I hate to say this, because it is so perverse, but there is an additional way to explicitly call the constructor.

class integer
{
   int m ,n;
 public:
   integer (int x , int y); 
};
integer :: integer (int x , int y )
{
   m=x; n = y;
}

The constructor can be explicitly called on an already-constructed object.

integer i(1,100);
i.~integer();
i.integer::integer(2,200);

Here I've constructed (explicitly) an instance of integer. Then I've explicitly called its destructor. Then I've explicitly called the constructor again. I suppose you might use this idiom in testing. I am not aware of any place in the standard that forbids it. It works in Visual Studio 2010. I haven't tested a really wide range of compilers.

These calls are explicit for large values of 'explicit'.

like image 39
seattlecpp Avatar answered Oct 31 '22 09:10

seattlecpp


There are three ways a constructor can be called:

  • Implicitly, by declaring an instance of the type without initializing it
  • Also implicitly, by either initializing an instance with = or by causing an implicit conversion from the argument type to your class.
  • Explicitly calling the constructor, passing arguments.

Which of these you can use in a particular context depends on the constructors you're calling.

class Foo 
{
    Foo();                                  // 1
    Foo(int a);                             // 2
    explicit foo(const std::string& f);     // 3
    Foo(int c, int d);                      // 4
};
  1. This constructor will be called implicitly when declaring Foo f;. Never attempt to call a constructor without arguments explicitly, as Foo f(); will declare a function!
  2. This one can be called by writing Foo f = 42; or Foo f(42).
  3. The explicit keyword forbids implicit conversion by writing Foo f = std::string("abc"); or function_taking_foo(function_returning_string());.
  4. As there are multiple arguments, the explicit version is the only suitable.
like image 60
Fabian Knorr Avatar answered Oct 31 '22 09:10

Fabian Knorr


There are two different problems here, as your definition of explicit and implicit does not match the standard definition (on which most of the existing answers are based, being written before you added your example containing your own definition of explicit and implicit).

Ok so let's first consider your definition of explicit, which would be (I guess you call it explicit because you explicitly write the type name?):

integer int1 = integer(0, 100);

versus your definition of implicit which would be:

integer int1(1, 100);

In this case the first "explicit" call really doesn't have any advantage over the second "implicit" call. But there is still a difference. The first one actually creates a temporary using the two-argument constructor, which is then used to create int1 using the copy constructor. Although in practice the compiler will usually optimize away this additional copy, it still won't work if your copy constructor is private, whereas the second one only needs the two-argument constructor (you could even see this as disadvantage).


But now to the actual standard definitions of explicit and implicit. An explicit constructor call is any constructor call you, well, explicitly call. Practically speaking, whenever you use the parenthesis syntax () to create an object you explicitly call a constructor, otherwise it's an implicit constructor call (so to say, being done behind the scenes by the compiler):

integer int1;                   // implicit default constructor
integer int1(1, 100);           // explicit two-arg constructor
integer int1 = integer(0, 100); // explicit two-arg constructor, implicit copy constructor

void func(integer);             // function taking by-value
func(int1);                     // implicit copy constructor

So the only constructors that can be called implicitly are the default construtor and any one-argument constructors (including copy and move constructors). A special problem in this regard are one-argument constructors not being copy/move constructors:

struct integer
{
    integer(int);
};

This allows the compiler to imlicitly call the the constructor to convert types, thus any int is implicitly convertible to integer:

void func(integer);
func(42);             // implicit call to int-constructor

To disallow such behaviour you would have to mark the constructor explicit:

struct integer
{
    explicit integer(int);
};

Which only allows it to be called explicitly (e.g. func(integer(42))) (but I guess you already knew this). This has the advantage that it doesn't introduce unnoticed/unwanted conversions behind the scenes, which can lead to all kinds of hard to find problems and ambiguities regarding overload resolution. It is therefore usual practice to mark any conversion constructors (one-argument non-copy/move constructors) explicit, and most probably also the reason why C++11 finally introduced explicit conversion operators.


So to sum up, according to your definition and example, there is really no advantage in using integer int1 = integer(1, 100); instead of integer int1(1, 100);, though it makes a (usually irrelevant) difference.

But according to the standard definitions, explicit constructor calls have plenty advantages over implicit ones, since the only way to actually construct an object explicitly is to use a, well, explicit constructor call, whereas implicit constructor calls are only done behind the scenes in certain situations and only work for zero- and one-argument constructors (as aschepler already pointed out). And explicitly marking conversion constructors as explicit has the advantage of disallowing unwanted implicit conversions behind the scenes.

like image 23
Christian Rau Avatar answered Oct 31 '22 10:10

Christian Rau