Допустим, мы собираемся создать класс, конструктор или конструкторы которого будут сохранены в переменной words
очень длинный номер:
class myClass {
private:
unsigned long long int words;
public:
...
}
Но я хочу иметь возможность инициализировать класс, используя любой встроенный тип, например:
int a; myClass A(a);
float b; myClass B(b);
long long int c; myClass C(c);
Должен ли я реализовать конструктор для каждого из типов (в списке Вот) в виде:
...
public:
...
myClass(const short int i):
words(i) {}
myClass(const unsigned short int i);
words(i) {}
etc...
Или я должен просто реализовать конструктор для unsigned long long int
:
...
public:
...
myClass(const unsigned long long int i):
words(i) {}
...
Я понимаю, что при использовании первого варианта (по одному для каждого) это произойдет:
int a; myClass(a);
// Call constructor myClass(const int i)
// Convert the value i to unsigned long long int and initialize words with it
Со вторым вариантом (один для всех):
int a; myClass(a);
// Convert i to unsigned long long int and this new value as a parameter for the constructor
// Initialize words with it
Теперь, какой я должен использовать? Я предполагаю, что лучше использовать один конструктор для unsigned long long int
,
Есть ли сценарий, где лучше иметь конструктор для каждого?
Единственная причина, по которой вы должны создавать более одного конструктора, это необходимость дополнительной логики обработки или преобразования. Например:
#include <string>
#include <iostream>
class myClass
{
public:
unsigned long long int words;// public for ease of example
// will consume anything convertable to unsigned long long
myClass(unsigned long long int val) :
words(val)
{
}
// will consume anything convertable to std::string, and then convert
// the string to unsigned long long
myClass(std::string val) :
words(std::stoull(val))
{
}
};
int main()
{
std::cout << myClass{ 10 }.words << ": 10" << std::endl;
std::cout << myClass{ -10 }.words << ": -10 (Two's compliment wrap)" << std::endl;
std::cout << myClass{ 3.14 }.words << ": 3.14 (Truncated)" << std::endl;
std::cout << myClass{ "10" }.words << ": \"10\"" << std::endl;
std::cout << myClass{ "-10" }.words << ": \"-10\" (Two's compliment wrap)" << std::endl;
}
10 конвертируется легко. -10 и 3.14 преобразуются, но будут генерировать предупреждения, потому что значение будет повреждено переводом. «10» и «-10» будут приняты string
-параметр, но «-10» будет искажен std::stoull
, Дополнительная логика и, возможно, использование strtoull
, будет необходимо обработать это, если требуется.
Я предложу реализовать один конструктор для unsigned long long it.
Причина в том, что:
выполнить код ниже. Код не будет компилироваться из-за неоднозначности.
Затем удалите конструктор int и соберите снова. Теперь код будет скомпилирован и успешно выполнен.
#include <iostream>
class myClass {
private:
unsigned long long int words;
public:
myClass(int i)
{
std::cout<<"in Int constructor"<<std::endl;
}
myClass(long long int i)
{
std::cout<<"in long constructor"<<std::endl;
}
};
int main()
{
myClass m(10000000000);
return 0;
}