可以为每个内置数据类型使用一个构造函数 C++
Is ok to have one constructor for each built in data types C++
假设我们要创建一个class,其构造函数或构造函数将在变量words
中保存一个很长的数字:
class myClass {
private:
unsigned long long int words;
public:
...
}
但我希望能够使用任何内置类型初始化 class,例如:
int a; myClass A(a);
float b; myClass B(b);
long long int c; myClass C(c);
我是否应该为每个类型(列出 here)实现一个构造函数,形式如下:
...
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
使用一个构造函数会更好。
是否有任何情况下每个都有一个构造函数更好?
我建议为 unsigned long long 实现一个构造函数。
原因是:
执行下面的代码。由于歧义,代码将无法编译。
然后删除 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;
}
您应该创建多个构造函数的唯一原因是需要额外的处理或转换逻辑。例如:
#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
来处理此问题。
假设我们要创建一个class,其构造函数或构造函数将在变量words
中保存一个很长的数字:
class myClass {
private:
unsigned long long int words;
public:
...
}
但我希望能够使用任何内置类型初始化 class,例如:
int a; myClass A(a);
float b; myClass B(b);
long long int c; myClass C(c);
我是否应该为每个类型(列出 here)实现一个构造函数,形式如下:
...
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
使用一个构造函数会更好。
是否有任何情况下每个都有一个构造函数更好?
我建议为 unsigned long long 实现一个构造函数。
原因是: 执行下面的代码。由于歧义,代码将无法编译。
然后删除 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;
}
您应该创建多个构造函数的唯一原因是需要额外的处理或转换逻辑。例如:
#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
来处理此问题。