0

I am still confused with the CTORs:

Question 1:
why line 15 call A:A(int) instead of A:A(double&)?

Question 2:
why line 18 did not call A:A(B&)?

#include <iostream> using namespace std; class B{}; class A{ public: A(int ) {cout<<"A::A(int)"<<endl;} A(double&){cout<<"A::A(double&)"<<endl;} // it will work if it is A(double), without the & A(B&){cout<<"A::A(B&)"<<endl;} }; int main() { /*line 15*/ A obj((double)2.1); // this will call A(int), why? B obj2; A obj3(obj2); /*line 18*/ A obj4(B); // this did not trigger any output why? } 
7
  • 1
    Most reasonable compilers would at least print out a warning about a double-to-int conversion. Commented Jul 21, 2011 at 18:33
  • @Kerrek: Yes. Yes, it does. (Though note the warning, and you will have to forgive codepad's -Werror.) Commented Jul 21, 2011 at 18:33
  • @Tomalak:Hah, I didn't know you can omit the parentheses for the default constructor. You can even say A x(int);... something new every day:-) Commented Jul 21, 2011 at 18:38
  • @Kerrek: Huh? You have to omit parentheses for the default constructor, otherwise you're declaring a function. Which is also what you're doing in A x(int);. Commented Jul 21, 2011 at 18:40
  • @Tomalak: You can also write A x(int());... Commented Jul 21, 2011 at 18:41

4 Answers 4

6

Line 15: A(double&) can only take lvalues, i.e. variables that can be assigned to. (double)2.1 is an rvalue. Use A(const double&) if you need to accept rvalues as reference too.

Line 18: B is a type, not a value. A obj4(B); only declares a function with name obj4 taking a B and returning an A.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks all for the fast response. I changed line 18 to be A obj4(B()), it is still not working. I then changed it to be A obj4((B())), then it works. Is A obj4(B()) still a function?
@John: Yes. It is a function called obj4 that takes a function with no name that takes nothing and returns a B, and returns an A. :) Read more.
Now I start to regret becoming a programmer :)
@John: Just wait until you get to templates! For what it's worth, you absorbed all these responses very quickly and from what I can tell, you understood them. So... good job!
3

Line 15

Your reference constructors accept only references to non-const objects.

That is, you wrote:

A(int) { cout<<"A::A(int)"<<endl; } A(double&) { cout<<"A::A(double&)"<<endl; } A(B&) { cout<<"A::A(B&)"<<endl; } 

instead of:

A(int) { cout<<"A::A(int)"<<endl; } A(double const&) { cout<<"A::A(double const&)"<<endl; } A(B const&) { cout<<"A::A(B const&)"<<endl; } 

The problem with this is that, in A obj((double)2.1), you invoked the constructors with temporary objects (in this case, the double literal 2.1 (that cast to double is pointless), and temporary objects may not bind to references that are not references to const.

So the A(double&) constructor cannot be called; the only one left that might match is A(int), and the required conversion is performed on your data (2.12) to make this happen. (Your compiler will normally warn you that this occurring.)

So, use the form of constructor that accepts reference to const.


Line 18

As for your A obj4(B), B is a type so you're declaring a function named obj4 that takes an (unnamed) B and returns an A.

Comments

0

Because & means it is a reference type and on line 15 you pass a value, not a reference.

15 Comments

You never "pass" a reference.
How would you go about passing a reference? I would be very interested :)
@Tomalak, Maybe I used the wrong words, but it does expect a reference and not a value. So, is my answer wrong?
@nightcracker, it's just a "phrase" commonly used where I mostly spend my days.. I mean that it expects a reference and he is "passing" hence "using"/"sending" or whatever word you want for it.
@Filip: I think you've confused terminology. You only ever pass "values" into functions; some functions copy them into new objects, others work with the existing objects ("accept by reference") and others just don't match at all... like this one. That's because you cannot bind the temporary/rvalue literal 2.1 to a reference parameter. But there is no way that you can fix that by "passing a reference" from the callsite.
|
-1

Line 15, the double is an rvalue (a temporary) and cannot convert to a non-const reference. For Line 18, the most likely explanation is that your compiler simply optimized out the constructor call.

4 Comments

If the compiler optimized it out then he must file a bug because the compiler is not allowed to optimize anything out that puts out output. I think KennyTM nailed it about line 18.
@Nightcracker: Constructors have special leeway in this regard.
@DeadMG: Nonsense. Line 18 doesn't even contain a constructor call.
@nightcracker: Unfortunately, though, constructors do have special semantics and can be optimised out even when they have side effects. It's pretty rubbish.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.