Различные аргументы в конструкторе класса в C++
Могу ли я заставить конструктор работать по-разному, если аргумент другого типа? т.е. int или float.
Скажем, если я это сделаю, new Object (3) конструктор заполняет массив 3 по каждому индексу
Скажем, если я это сделаю, новый объект (3.5) конструктор заполняет массив с индексом + 3.5 для каждого индекса
Скажем, если я это сделаю, new Object () конструктор заполняет массив 0,0 по каждому индексу.
Есть ли способ добиться этого с помощью всего одного конструктора? Или мне нужно три разных конструктора?
Спасибо.
Ответов (12)12
Конечно, у вас может быть много конструкторов! Перегрузка конструкторов работает так же, как и для любой функции / члена.
Просто помните, что иногда компилятор может неявно вызывать конструктор, который вы не хотели бы вызывать, - путем автоматического преобразования аргументов.
Вы можете добавить ключевое слово явным образом в объявление конструктора, чтобы запретить автоматическое преобразование.
Пока переданный параметр всегда относится к одному типу, вы можете обойтись одним конструктором, в противном случае вам понадобится несколько.
Кажется, что наиболее очевидным решением этой проблемы было бы вставить оператор 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
};
Похоже, вас ждет кошмар обслуживания. Я предлагаю вместо этого использовать идиому именованного конструктора:
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);
};