user2664344
user2664344

Reputation: 179

C++: how to pass a variable as an argument to class constructor

I am faced with a very puzzling issue. I am trying to construct an object using a variable as a parameter.

Have a look at this code please:

#include <iostream>

class A {

  public:
    A()      : val(0) {};
    A(int v) : val(v) {};

  private:
    int val;
};

main() {

  int number;

  A a;       /* GOOD, object of type A, created without arguments */
  A b(2);    /* GOOD, object of type A, created with one argument */
  A c();     /* BAD, C++ thinks this is declaration of
                a function returning class A as a type */
  A(d);      /* GOOD, object of type A again; no arguments */
  A(number); /* BAD, tries to re-declare "number" as object of type A */
}

I think I do understand why objects "a", "b" and "d" can be created, whereas the rest can not.

But I would really need the syntax of the last declaration, i.e.

    A(number);

to create a temporary object, to pass as an argument to another object.

Any idea how to work around it?

Kind regards

Upvotes: 4

Views: 8924

Answers (1)

Ad N
Ad N

Reputation: 8376

Your intention is to create a temporary object, but this object would also be anonymous : you have no way to refer to it after the semicolon. There is no point in creating an anonymous temporary object just to discard it. You have to instantiate your temporary directly at the call site of the ctor/method that will consume it.

Solution

To pass an anonymous temporary object to a function, you actually need to instantiate it inside the arguments' list :

functionExpectingA(A(number));

For the line of "c declaration", you are poking at the most vexing parse. If you actually need to pass a default constructed A object as an argument to another object constructor, you need to add another pair of braces to do the trick (so the compiler can distinguish it from a function declaration) :

class OtherClass
{
public:
    OtherClass(A a)
    {
         //...
    };
};

OtherClass obj((A()));
               ^   ^

EDIT #1 : jrok pointed out that the argument given to A constructor is not enough to resolve the ambiguity.

If you need to pass an anonymous temporary object that is built with an argument, there is no ambiguity (so no need for the extra parentheses), you still need the parentheses around the anonymous object construction.:

OtherClass obj((A(number)));

C heritage : a single argument is not enough

EDIT #2 : "why giving a single argument to A constructor does not resolve the ambiguity".

What happens with OtherClass obj(A(number)); ?
This is a declaration for a function named obj, taking an A object as its unique argument. This argument is named number.
i.e: It is exactly equivalent to OtherClass obj(A number);. Of course, you can omit the argument name at function declaration. So it is also sementically equivalent to OtherClass obj(A);

The syntax with parentheses around the object name is inherited from C :

int(a); // declares (and defines) a as an int.
int a;  // strictly equivalent.

What with more arguments to the constructor then ?

If you added a ctor to OtherClass taking two (or more) arguments :

    OtherClass(A a1, A a2)
    {
         //...
    };

Then this syntax :

A arg1, arg2;
OtherClass obj(A(arg1, arg2));

Would this time actually declare obj as an instance of OtherClass.
This is because A(arg1, arg2) cannot be interpreted as name declaration for an A. So it is actually parsed as the construction of an anonymous A object, using the constructor with 2 parameters.

Upvotes: 1

Related Questions