Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > conversion constructor called twice - why?

Reply
Thread Tools

conversion constructor called twice - why?

 
 
Alexander Stippler
Guest
Posts: n/a
 
      10-30-2005
Given the following code snippet we get some unexpected behaviour:
//--------------------------------------------------------------------
#include <iostream>

using namespace std;

struct A
{
A() { cerr << "A()" << endl; }
};

struct C;

struct B : public A
{
B();

explicit
B(const B &rhs);

B(const A&rhs);

C
operator()(int from, int to);
};

struct C: public A
{
B r;

operator const B &() const;
};

B::B() { cerr << "B()" << endl; }

B::B(const B &rhs)
{ cerr << "B(const B &rhs)" << endl; }

B::B(const A &rhs)
{ cerr << "B(const A &rhs)" << endl; }

C
B:perator()(int from, int to) { return C(); }

C:perator const B &() const
{ cerr << "operator const B &() const" << endl;
return r;
}

int main()
{
C c;
B b = c; // conversion constructor called twice here - why??
return 0;
}
//--------------------------------------------------------------------

The conversion constructor B(const A &) is called twice when
initializing object b. We would expect a call of
C:perator const B &() const
and then one call of
B::B(const B &).


 
Reply With Quote
 
 
 
 
Valentin Samko
Guest
Posts: n/a
 
      10-31-2005
Alexander Stippler wrote:
> struct B : public A
> {
> explicit
> B(const B &rhs);
>
> B(const A&rhs);
>
> };


> B b = c; // conversion constructor called twice here - why??


> The conversion constructor B(const A &) is called twice when
> initializing object b. We would expect a call of
> C:perator const B &() const
> and then one call of
> B::B(const B &).


The call to B::B(const B&) is not happening because that copy constructor is explicit.

Regarding calling this constructor twice - See 8.5/14 "Otherwise (i.e. for the remaining...".

Since your copy constructor in B is explicit, so the compiler chooses another path, i.e.
1. "c" is casted to A&
2. a temporary of class B is created from the result via the "B(const A&)" constructor.
3. your "b" is initialised with that temporary.

--

Valentin Samko - http://www.valentinsamko.com
 
Reply With Quote
 
 
 
 
Greg
Guest
Posts: n/a
 
      10-31-2005

Valentin Samko wrote:
> Alexander Stippler wrote:
> > struct B : public A
> > {
> > explicit
> > B(const B &rhs);
> >
> > B(const A&rhs);
> >
> > };

>
> > B b = c; // conversion constructor called twice here - why??

>
> > The conversion constructor B(const A &) is called twice when
> > initializing object b. We would expect a call of
> > C:perator const B &() const
> > and then one call of
> > B::B(const B &).

>
> The call to B::B(const B&) is not happening because that copy constructor is explicit.
>
> Regarding calling this constructor twice - See 8.5/14 "Otherwise (i.e. for the remaining...".
>
> Since your copy constructor in B is explicit, so the compiler chooses another path, i.e.
> 1. "c" is casted to A&
> 2. a temporary of class B is created from the result via the "B(const A&)" constructor.
> 3. your "b" is initialised with that temporary.


No, there is no temporary. Two user-defined conversions would be one
more than is allowed. Besides, there is no need of a B temporary since
B has a constructor that accepts an A object directly. So b is
constructed from an A class object (namely, c).

Greg

 
Reply With Quote
 
Valentin Samko
Guest
Posts: n/a
 
      10-31-2005
Greg wrote:
> Valentin Samko wrote:
>> Alexander Stippler wrote:
>>> struct B : public A
>>> {
>>> explicit
>>> B(const B &rhs);
>>>
>>> B(const A&rhs);
>>>
>>> };
>>> B b = c; // conversion constructor called twice here - why??
>>> The conversion constructor B(const A &) is called twice when
>>> initializing object b. We would expect a call of
>>> C:perator const B &() const
>>> and then one call of
>>> B::B(const B &).

>> The call to B::B(const B&) is not happening because that copy constructor is explicit.
>>
>> Regarding calling this constructor twice - See 8.5/14 "Otherwise (i.e. for the remaining...".
>>
>> Since your copy constructor in B is explicit, so the compiler chooses another path, i.e.
>> 1. "c" is casted to A&
>> 2. a temporary of class B is created from the result via the "B(const A&)" constructor.
>> 3. your "b" is initialised with that temporary.

>
> No, there is no temporary. Two user-defined conversions would be one
> more than is allowed. Besides, there is no need of a B temporary since
> B has a constructor that accepts an A object directly. So b is
> constructed from an A class object (namely, c).


Please read 8.5/14. The right hand side has to be converted to the destination type (B)
first. Only after the rhs is converted, compiler picks the most appropriate constructor.

Besides, no used-defined conversions happen.

--

Valentin Samko - http://www.valentinsamko.com
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
A constructor calling another constructor (default constructor)? Generic Usenet Account C++ 10 11-28-2007 04:12 AM
twice(twice(x)) Kiuhnm C++ 2 04-01-2006 04:41 PM
Why is copy constructor called only twice here (should be thrice?) TechCrazy C++ 5 07-15-2005 10:15 AM
Global constructor called twice Manuel Vázquez Acosta ASP .Net 1 01-22-2005 05:15 AM
Why is the Base class Constructor getting called twice Robert C++ 6 12-11-2003 12:06 PM



Advertisments