简体   繁体   中英

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? ie 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.

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.

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.

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);
};

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
    }
};

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;
}

}

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
};

You need 3 different constructors.

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

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.

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.

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)
};

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM