user69699
user69699

Reputation: 63

Different arguments in the Constructor of a class in C++

Can I have a constructor work in different ways if the argument is of different type? i.e. int or float.

Let's say that if I do, new Object(3) the constructor fills an array with 3 at every index

Let's say that if I do, new Object(3.5) the constructor fills an array with index+3.5 for every index

Let's say that if I do, new Object() the constructor fills an array with 0.0 at every index

Is there a way to achieve this with just one constructor? Or do I need three different constructors?

Thanks.

Upvotes: 1

Views: 3681

Answers (12)

Corey Sunwold
Corey Sunwold

Reputation: 10254

As long as the parameter passed is always of the same type you can get away with using one constructor, otherwise you need several.

It seems as though the most obvious solution to this would be to insert a switch statement inside your object constructor.

Example:

public Object(int num)
{
switch (num)
{
case 1: array[i]  = num;
break
case 2: array[i] = num * 2;
}

}

Upvotes: 1

Johann Gerell
Johann Gerell

Reputation: 25581

It sounds like you're up for a maintenance nightmare. I suggest yo use the named constructor idiom instead:

class Object
{
public:
    // Sets all elements to 0.
    Object();

    // Sets all elements to value.
    static Object Fill(double value);

    // Sets all elements to the previous + delta, beginning at start.
    static Object Accumulate(double start, double delta);
};

Upvotes: 2

CB Bailey
CB Bailey

Reputation: 792089

It is usually a bad idea to have such different behaviour for a constructor purely based on the type of the parameter, especially for built-in types that are easily implicitly convertible between each other.

Having said that, purely as a programming exercise, it is possible to do this using one constructor, but you would have to use a proxy class with implicit conversion from the types to be distinguished between to achieve what you want. As a pre-canned solution, boost::variant would fit the requirement. You may not consider this to meet the requirements of a single constructor, as it relies on multiple constructors (or a constructor template) of a second class.

class Object
{
public:
        Object( const boost::variant< int, double >& val = 0 )
        {
                switch( val.which() )
                {
                case 0:
                        // TODO: Fill array with val
                        break;
                case 1:
                        // TODO: fill array with val + index
                        break;
                }
        }

// TODO: Add array member
};

Upvotes: 1

Naveen
Naveen

Reputation: 73443

Use 3 different constructors as the logic is different depending upon the type of the parameter. Also, be aware of the type promotions done by the compiler..otherwise you might end up with surprises when the code is executed.

Upvotes: 0

random
random

Reputation: 95

You can factor the behavior Object() and Object(3) because they do the same thing. Just write your constructor like this:

class Object {
    // fills an array with n at every index
    Object(int n = 0) { ... }
};

The problem is that the constructor with a float (3.5 in the example) has to be separated, like this:

class Object {
    // fills an array with n at every index
    Object(int n = 0) { ... } // handles Object() AND Object(3)

    // fills an array with index + n at every index
    Object(float n)   { ... } // handles Object(3.5)
};

Upvotes: 0

Franci Penov
Franci Penov

Reputation: 76001

No only you need three different constructors, you want three different constructors. It'll keep the code cleaner and easier to understand, maintain and unit test.

Upvotes: 0

Marcin Gil
Marcin Gil

Reputation: 69505

Of course you can have many constructors! Overloading for constructors work the same as for any function/member.

Just remember that sometimes compiler can implicitly call a constructor that you wouldn't like to have been called - by automatic conversion of arguments.

You can add keyword explicit to the constructor declaration to forbid any automatic conversion.

Upvotes: 7

Ido Weinstein
Ido Weinstein

Reputation: 1168

You can do it with one constructor, but it will be ugly as hell. A 3 constructors approach is proffered because it separates the usage and simplify the code.

Upvotes: 3

Andrew Khosravian
Andrew Khosravian

Reputation: 1099

If you only care about built in types you can take advantage of type promotions and default values:

struct Object
{
    Object(double value = 0.0)
    {
        // do that thing you do
    }
};

Upvotes: 1

David Božjak
David Božjak

Reputation: 17627

You will either need three different constructors (overloading them) or one with some attributes with default values.

This can be achieved, however I would suggest using 3 different constructors for code clarity, etc.

Upvotes: 0

Alex B
Alex B

Reputation: 24936

Multiple constructors would be required, one for each different argument type.

Upvotes: 0

Andrew Coleson
Andrew Coleson

Reputation: 10320

You need 3 different constructors.

Upvotes: 0

Related Questions