为什么我的赋值运算符没有被调用?
我很困惑...为什么我的赋值运算符没有在这里被调用?
template<typename This>
struct mybase
{
This& operator =(const This &other)
{
__debugbreak(); // The debugger should break here, but doesn't.
return static_cast<This &>(*this):
}
};
struct myderived : mybase<myderived>
{
int x;
};
int main()
{
myderived a = myderived(); // And yes, I know it's redundant...
myderived b = myderived();
a = b;
return 0;
}
I'm confused... why isn't my assignment operator getting called here?
template<typename This>
struct mybase
{
This& operator =(const This &other)
{
__debugbreak(); // The debugger should break here, but doesn't.
return static_cast<This &>(*this):
}
};
struct myderived : mybase<myderived>
{
int x;
};
int main()
{
myderived a = myderived(); // And yes, I know it's redundant...
myderived b = myderived();
a = b;
return 0;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
因为派生中的默认赋值运算符会隐藏基中的重载。
Because the default assignment operator in derived will hide the overloaded in base.
mybase::operator=
被自动生成的复制赋值运算符mydriven::operator=
隐藏。您可以使用
using
声明使基类运算符在派生类中可见。编辑:根据请求添加了示例:
这可以使用 Visual C++ 10.0 和 Comeau Online 进行良好的编译。后者实际上意味着它是良好的标准 C++。但是,该代码无法使用 MinGW g++ 4.4.1 进行编译(编译器错误)。
编辑2:实际上,现在检查,使用 Visual C++ 10.0 它可以编译,但不会调用基类运算符。所以也许 g++ 是正确的。
using
通常是引入基类赋值运算符(或其他)的方法,但在这种情况下,它与派生类的复制赋值运算符具有相同的签名,我还不知道是否Visual C++ 行为正确与否 – 这是该语言的一个极端情况。编辑3:我检查了N3290(与C++11相同的标准草案),它说
我个人将此解释为,通过使用
using
声明,类“声明”了一个复制赋值运算符,因此不应该隐式生成该运算符(Visual C++ 10.0 似乎是这样做的)。然而,这是该语言的一个极端情况。其他人可能会对此有不同的解释,并且如上所述,编译器有所不同!干杯&呵呵,,
mybase::operator=
is hidden by the automatically generated copy assignment operatormyderived::operator=
.You can use a
using
declaration to make the base class operator visible in the derived class.EDIT: added example per request:
This compiles fine with Visual C++ 10.0 and with Comeau Online. The latter means, in practice, that it's good standard C++. However, the code does not compile with MinGW g++ 4.4.1 (compiler bug).
EDIT 2: Actually, checking now, with Visual C++ 10.0 it compiles but the base class operator is not invoked. So maybe g++ is correct.
using
is generally the way to bring in a base class assignment operator (or whatever), but in this case it has the same signature as the derived class’ copy assignment operator, and I do not yet know whether Visual C++ behavior is correct or not – it is a corner case of the language.EDIT 3: I checked N3290 (the standard draft that is identical to C++11), and it says
I personally interpret that as saying that with the
using
declaration in place the class “declares” a copy assignment operator, and that one should therefore not be implicitly generated (as it seems that Visual C++ 10.0 does). However, this is a corner case of the language. Others may possibly interpret this differently, and as noted above, compilers differ!Cheers & hth.,
这行:
显然要求
my衍生
已经重载了复制赋值运算符。它可以由编译器隐式生成,也可以由mydriven
类显式定义:您尝试在
mybase
类中创建用户声明的复制赋值运算符,但根据 C++ 标准,它实际上并不是复制赋值运算符。想象一下,如果我们用my衍生
对This
进行类型替换:显然这不是复制赋值运算符,因为参数
other
的类型是>const my衍生&
,而不是const mybase&
。如果other
参数的类型为const mybase&
、mybase
或mybase&
,那么它将是有效的复制赋值运算符,可以由my衍生
中的默认复制赋值运算符调用。但本例并非如此,因此编译器仍然为mybase
生成默认的复制赋值运算符,当然在本例中它不执行任何操作。my衍生
中编译器生成的默认复制赋值运算符调用mybase
中编译器生成的默认复制赋值运算符。那么最终会发生什么,结果是,operator=(const mydriven &other) 重载永远不会被调用。编译器不直接调用
mybase::operator=
的原因是因为它被编译器生成的mydriven
中的复制赋值运算符隐藏了,如 Alf P.斯坦巴赫在这个答案。This line:
obviously requires that
myderived
have overloaded the copy assignment operator. It can be implicitly generated by the compiler, or defined by themyderived
class explicitly:You have attempted to create a user-declared copy assignment operator in your
mybase
class, but it's not actually a copy assignment operator according to the C++ standard. Imagine if we did a type substitution forThis
withmyderived
:Clearly that's not a copy assignment operator, because the parameter
other
is of typeconst myderived&
, notconst mybase&
. Had theother
parameter be of typeconst mybase&
, ormybase
, ormybase&
, then it would be a valid copy assignment operator, which can be called by the default copy assignment operator inmyderived
. But it isn't in this case, so the compiler still generates a default copy assignment operator formybase
, which of course does nothing in this case.The compiler-generated default copy assignment operator in
myderived
calls the compiler-generated default copy assignment operator inmybase
. So what ends up happening, as As a result, theoperator=(const myderived &other)
overload is never called.The reason why the compiler doesn't just call
mybase::operator=
directly is because it's been hidden by the compiler-generated copy assignment operator inmyderived
, as Alf P. Steinbach points out in this answer.因为编译器在my衍生中引入了默认的赋值运算符。重写它并自己调用您的基本赋值运算符。或者也许 using 指令会有帮助?尝试在 my衍生体中使用 mybase::operator= 。
Because the compiler introduces the default assignment operator in myderived. Override it and call your base assignment operator yourself. Or perhaps a using directive will help? Try using mybase::operator= in myderived body.