Let's say we are going to create a class whose constructor or constructors will save in the variable words
a very long number:
class myClass {
private:
unsigned long long int words;
public:
...
}
But I want to be able to initialize the class using any built-in type, for example:
int a; myClass A(a);
float b; myClass B(b);
long long int c; myClass C(c);
Should I implemeting a constructor for each one of the types (listed here) in the form:
...
public:
...
myClass(const short int i):
words(i) {}
myClass(const unsigned short int i);
words(i) {}
etc...
Or should I just implement the constructor for unsigned long long int
:
...
public:
...
myClass(const unsigned long long int i):
words(i) {}
...
What I understand is that using the first option (one for each), this will happen:
int a; myClass(a);
// Call constructor myClass(const int i)
// Convert the value i to unsigned long long int and initialize words with it
With the second option (one for all):
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
Now, which one should I use ?. I'm guessing it's just better to use one constructor for unsigned long long int
.
Is there any scenario where this having a constructor for each one is better?
The only reason you should make more than one constructor is if extra handling or conversion logic is required. For example:
#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 is converted easily. -10 and 3.14 are converted, but will generate warnings because the value will be damaged by the translation. "10" and "-10" will be accepted by the string
-parametered constructor, but "-10" will be mangled by std::stoull
. Additional logic, and probably use of strtoull
, will be required to handle this, if required.