By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
454,435 Members | 1,499 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 454,435 IT Pros & Developers. It's quick & easy.

conversion constructor called twice - why?

P: n/a
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::operator()(int from, int to) { return C(); }

C::operator 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::operator const B &() const
and then one call of
B::B(const B &).
Oct 30 '05 #1
Share this Question
Share on Google+
3 Replies


P: n/a
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::operator 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
Oct 31 '05 #2

P: n/a

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::operator 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

Oct 31 '05 #3

P: n/a
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::operator 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
Oct 31 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.