Различные аргументы в конструкторе класса в C++

Могу ли я заставить конструктор работать по-разному, если аргумент другого типа? т.е. int или float.

Скажем, если я это сделаю, new Object (3) конструктор заполняет массив 3 по каждому индексу

Скажем, если я это сделаю, новый объект (3.5) конструктор заполняет массив с индексом + 3.5 для каждого индекса

Скажем, если я это сделаю, new Object () конструктор заполняет массив 0,0 по каждому индексу.

Есть ли способ добиться этого с помощью всего одного конструктора? Или мне нужно три разных конструктора?

Спасибо.

Ответов (12)

Вам нужны не только три разных конструктора, вам нужны три разных конструктора. Это сделает код более чистым и простым для понимания, обслуживания и модульного тестирования.

Вам понадобятся либо три разных конструктора (перегружающие их), либо один с некоторыми атрибутами со значениями по умолчанию.

Этого можно достичь, однако я бы предложил использовать 3 разных конструктора для ясности кода и т. Д.

Вы можете сделать это с помощью одного конструктора, но это будет чертовски уродливо. Предлагается подход с использованием трех конструкторов, поскольку он разделяет использование и упрощает код.

Конечно, у вас может быть много конструкторов! Перегрузка конструкторов работает так же, как и для любой функции / члена.

Просто помните, что иногда компилятор может неявно вызывать конструктор, который вы не хотели бы вызывать, - путем автоматического преобразования аргументов.

Вы можете добавить ключевое слово явным образом в объявление конструктора, чтобы запретить автоматическое преобразование.

Вам понадобится 3 разных конструктора.

Если вас интересуют только встроенные типы, вы можете воспользоваться продвижением типов и значениями по умолчанию:

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

Пока переданный параметр всегда относится к одному типу, вы можете обойтись одним конструктором, в противном случае вам понадобится несколько.

Кажется, что наиболее очевидным решением этой проблемы было бы вставить оператор switch в конструктор вашего объекта.

Пример:

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

}

Вы можете учитывать поведение Object() и Object(3) потому, что они делают то же самое. Просто напишите свой конструктор так:

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

Проблема в том, что конструктор с плавающей точкой (в примере 3.5) должен быть отделен, например:

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

Потребуется несколько конструкторов, по одному для каждого типа аргумента.

Обычно плохая идея - иметь такое разное поведение для конструктора, основанное исключительно на типе параметра, особенно для встроенных типов, которые легко неявно конвертируются друг в друга.

Сказав это, чисто в качестве упражнения по программированию, это можно сделать с помощью одного конструктора, но вам придется использовать прокси-класс с неявным преобразованием типов, которые нужно различать, чтобы достичь желаемого. Как готовое решение, boost :: variant подойдет под это требование. Вы можете не рассматривать это как соответствие требованиям одного конструктора, поскольку он полагается на несколько конструкторов (или шаблон конструктора) второго класса.

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

Используйте 3 разных конструктора, поскольку логика различается в зависимости от типа параметра. Кроме того, помните о повышении типов, выполняемых компилятором ... в противном случае вы можете столкнуться с сюрпризами при выполнении кода.

Похоже, вас ждет кошмар обслуживания. Я предлагаю вместо этого использовать идиому именованного конструктора:

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