前几天我在一位同事的代码中偶然发现了一些事情,我想知道这是如何/为何有效。
他使用像这样的结构
struct my_struct
{
my_struct(){ /* default constructor*/};
my_struct(char c){ /*some special constructor*/};
// other stuff
my_struct& operator=(const my_struct &ms){ /* assignment */};
};
最初通过拼写错误,他发现以下作品
my_struct ms;
double a;
ms = a;
我已经知道这是相同的(在给出相同的最终结构ms的意义上)到下面的
my_struct ms;
double a;
my_struct ms2((char) a);
ms=ms2;
但我不知道为什么。就个人而言,我认为这不应该工作,因为double和my_struct没有赋值运算符,另外因为my_struct没有使用double的构造函数。
我试图谷歌这个,但没有找到任何相关的。
@ user657267:我想让它尽可能短,你可以添加一行a = 5;或者无论如何都适用。
答案 0 :(得分:4)
在编译期间:
ms = a;
尝试解决以下一个或多个直接表单的分配
my_struct& operator ()(double)
my_struct& operator ()(double&)
my_struct& operator ()(const double&)
以及来自double
的一连串其他潜在转化。没有找到。事实上,只发现了以下内容:
my_struct& operator=(const my_struct &ms)
表示编译器允许通过另一个my_struct
的const-reference进行赋值。那时会寻找转换构造函数,从最直接的转换开始(显式转换为类型double
:
my_struct(double)
my_struct(double&)
my_struct(const double&)
重要的是要注意这样的构造函数不能强制显式使用。我们隐含地构建了一个临时的,因此明确的授权不在保留范围之内。
无论如何,再一次,没有找到。在放弃编译器之前,尝试找到任何形式的构造函数,该构造函数可以从double
转换为基本构造所需的和所述构造函数支持隐式构造。实际上,形式
my_struct(<<something that can be converted from a double>>)
同样,构造函数不能是explicit
。事实证明,此搜索确实找到了这个:
my_struct(char)
因为double
可以转换为char
(虽然很差,很可能不是你想要的)。整个链条有点(好吧,很多)比这更复杂,但这就是它的关键。
你可以通过确保构造函数在使用中仅explicit
来避免这种隐式构造,但这是一个双刃剑,所以需要小心。使用explicit
可能有点苛刻。这样做:
explicit my_struct(char)
将double
转换为char
时,会压制意外的隐式构造。但我警告你;它还会压制这样做的能力:
char x = 'a';
my_struct ms;
ms = x;
因为my_struct
现在char
无法通过转换或其他方式从double
隐式构建 。有多种方法可以解决此问题,包括为类型定义特定的赋值运算符(采用double
)或特定的转换构造函数(采用{{1}})。你离开的方式如何接近你。
答案 1 :(得分:3)
你自己有一个转换构造函数:
my_struct(char c)
这意味着可以转换为char
的任何内容都可以用于隐式创建my_struct
的对象。
为了避免这种情况,您可以将explicit
添加到构造函数中:
explicit my_struct(char c)
这样你就可以像这样从双方创建一个对象:
double a = my_initial_value;
my_struct ms2(a);
此外,始终初始化变量,否则int
,float
,指针等类型将保留随机值。