# C++ Constructor Arcane-ness :)

## Recommended Posts

discman1028    212
Hey all, I had never seen this C++ feature before until someone mentioned it the other day:
class A;
class B;

void main()
{
B obj("hello");  // This actually calls B::B(A::A("hello"))
}

class B
{
B(A obj) { ... }
};

class A
{
A(char * str) { ... }
};

This example might not be syntactically correct, but it's the idea. Anyone actually use this for something useful? (What is a use?) discman1028

##### Share on other sites
Roboguy    794
Probably so things like this don't generate errors:
#include <string>int main() {    A a("example");    ...}struct A {    A(std::string string) { ... }    ...};

##### Share on other sites
bballmitch    100
umm...I see how that works, but I can't think of ANY situation where that would be useful. :(

##### Share on other sites
discman1028    212
Ah! That's a good one I never thought about. :) (@Roboguy)

##### Share on other sites
smart_idiot    1298
It's kind of a side effect of something else entirely.

Constructors that take a single argument and aren't marked as explicit get used for implicit type conversions. That is, due to A's constructor, the compiler now knows how to automatically turn a character pointer into an A object.

In your example, B's constructor expects and A object, but you pass a character pointer. The compiler knows how to create an A object from a character pointer, so it does the conversion for you, so it works.

It doesn't have to be a constructor; it will automatically convert types for all functions and operators if the types aren't what it expects, and there is only one possible way to do it; otherwise it will complain about ambiguity.

It is a useful feature, it can save you writing code for every possible way something might be used, or having to cast everything to the proper type. It can also be an unobvious way to lose performance, because functions are going to end up being called and objects created that isn't obvious when you look at the code.

##### Share on other sites
discman1028    212
Thanks!

Quote:
 Original post by smart_idiotIt can also be an unobvious way to lose performance, because functions are going to end up being called and objects created that isn't obvious when you look at the code.

Though, it would only be unobvious that an object is being created if the programmer used this methodology by accident. Then again, I guess they could know the feature without knowing what's going on, too.

##### Share on other sites
Bregma    9214
Quote:
 Original post by bballmitchumm...I see how that works, but I can't think of ANY situation where that would be useful. :(

struct Point{  Point(double x, double y)  : m_x(x), m_y(y)  { }  double m_x;  double m_y;}Point origin(0, 0);

Wouldn't you be surprized if that didn't compile?

##### Share on other sites
Guest Anonymous Poster
Just thought I would add how you can prevent that behaviour as it's not always desirable.

class A;
class B;

void main()
{
B obj("hello"); // Error, A::A(char*) is marked explicit
}

class B
{
B(A obj) { ... }
};

class A
{
explicit A(char * str) { ... }
};

##### Share on other sites
discman1028    212
Quote:
Original post by Bregma
Quote:
 Original post by bballmitchumm...I see how that works, but I can't think of ANY situation where that would be useful. :(

struct Point{  Point(double x, double y)  : m_x(x), m_y(y)  { }  double m_x;  double m_y;}Point origin(0, 0);

Wouldn't you be surprized if that didn't compile?

I would have been surprised if that compiled, since no constructor is made for type double! I did not know that was possible. I would be less surprised, in this shown case though, since I can understand implicit casting from int to double. But from a POD (plain old datatype) to an object, via a constructor, I was surprised.

By the way, I believe this property may only be "nested" a couple times (only a couple constructor levels down). I haven't tested it, it's just whaty I heard from my source.

@Anonymous Poster: Yep, that 'explicit' keyword is good to know! Thanks to the posters here for letting me know about it!

##### Share on other sites
njpaul    367
Ah, but there is, although I don't know if it officially is a constructor. That is why the following code works.

#include <iostream>using namespace std;int main(void){	double d(4.5);	int i(3);	cout << "d = " << d << ", i = " << i << endl;	return 0;}

##### Share on other sites
Fruny    1658
Quote:
 I would have been surprised if that compiled, since no constructor is made for type double!

There is an implicit promotion from int to double. This code should compile.

I did not know that was possible. I would be less surprised, in this shown case though, since I can understand implicit casting from int to double.

Quote:
 But from a POD (plain old datatype) to an object, via a constructor, I was surprised.

Single parameter constructors are known as conversion constructors. They are the counterpart of conversion operators.

Quote:
 By the way, I believe this property may only be "nested" a couple times (only a couple constructor levels down).

The implicit conversion chain can only contain one user-defined conversion.

Quote:
 @Anonymous Poster: Yep, that 'explicit' keyword is good to know! Thanks to the posters here for letting me know about it!

Single-parameter constructors should be marked explicit unless you know you want them to act as conversion constructors.

##### Share on other sites
Bregma    9214
Quote:
 Original post by discman1028I can understand implicit casting from int to double. But from a POD (plain old datatype) to an object, via a constructor, I was surprised.

There is no implicit cast from int to double. There is an implicit type conversion, though. A cast and a type conversion are two different things. Perhaps that's why you're surprized.

One of the guiding principals in C++ is "what would int do?" (WWID). Okay, so maybe I just made up that expression, but the pricipal is there. In the example I gave, the int is automatically converted to a double. It would be the same if there was a conversion constructor for a non-pod type. Do what the ints do.

The overload resolution rules are, in order:

(1) exact match

(2) match using a promotion (eg. bool to int, flot to double, etc)

(3) match using a standard conversion (eg. int to double, Derived* to Base*, etc)

(4) match using user-defined conversion (conversion constructor, cast operator())

(5) match using the ellipsis

More than one match at the same level is an ambiguity error.

##### Share on other sites
Guest Anonymous Poster
Quote:
 Original post by Bregma"what would int do?" (WWID)

I believe "Do as the ints do" is more common, but yours is certainly more amusing [grin]

##### Share on other sites
discman1028    212
Quote:
Original post by Bregma
Quote:
 Original post by discman1028I can understand implicit casting from int to double. But from a POD (plain old datatype) to an object, via a constructor, I was surprised.

There is no implicit cast from int to double. There is an implicit type conversion, though. A cast and a type conversion are two different things. Perhaps that's why you're surprized.

Nope that's not why, I meant implicit conversion, but used "cast" lazily. Just surprized b/c I've never seen it before.

Quote:
Original post by Fruny
Quote:
 I would have been surprised if that compiled, since no constructor is made for type double!

There is an implicit promotion from int to double. This code should compile.

Let's just say, I would have been surprised 48 hours ago...

Thanks all!

## Create an account

Register a new account