operator= 和 C++ 中未继承的函数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12009865/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
operator= and functions that are not inherited in C++?
提问by Vincent
Until a test I've just made, I believed that only Constructors were not inherited in C++. But apparently, the assignment operator=
is not too...
在我刚刚进行的测试之前,我相信只有构造函数在 C++ 中没有被继承。但显然,这个任务operator=
并不太...
- What is the reason of that ?
- Is there any workaround to inherit the assignment operator ?
- Is it also the case for
operator+=
,operator-=
, ... ? - Are all other functions (apart from constructors/operator=) inherited ?
- 那是什么原因呢?
- 是否有任何解决方法来继承赋值运算符?
operator+=
,operator-=
, ...也是这种情况吗?- 所有其他函数(除了构造函数/operator=)是否都是继承的?
In fact, I encountered this problem as I was doing some CRTP :
事实上,我在做一些 CRTP 时遇到了这个问题:
template<class Crtp> class Base
{
inline Crtp& operator=(const Base<Crtp>& rhs) {/*SOMETHING*/; return static_cast<Crtp&>(*this);}
};
class Derived1 : public Base<Derived1>
{
};
class Derived2 : public Base<Derived2>
{
};
Is there any solution to get that working ?
有没有办法让它工作?
EDIT : OK, I have isolated the problem. Why the following isn't working ? How to solve the problem ?
编辑:好的,我已经隔离了问题。为什么以下不起作用?如何解决问题?
#include <iostream>
#include <type_traits>
// Base class
template<template<typename, unsigned int> class CRTP, typename T, unsigned int N> class Base
{
// Cast to base
public:
inline Base<CRTP, T, N>& operator()()
{
return *this;
}
// Operator =
public:
template<typename T0, class = typename std::enable_if<std::is_convertible<T0, T>::value>::type>
inline CRTP<T, N>& operator=(const T0& rhs)
{
for (unsigned int i = 0; i < N; ++i) {
_data[i] = rhs;
}
return static_cast<CRTP<T, N>&>(*this);
}
// Data members
protected:
T _data[N];
};
// Derived class
template<typename T, unsigned int N> class Derived : public Base<Derived, T, N>
{
};
// Main
int main()
{
Derived<double, 3> x;
x() = 3; // <- This is OK
x = 3; // <- error: no match for 'operator=' in ' x=3 '
return 0;
}
采纳答案by eq-
The assignment operator is technically inherited; however, it is always hidden by an explicitly or implicitly defined assignment operator for the derived class (see comments below).
赋值运算符在技术上是继承的;然而,它总是被派生类的显式或隐式定义的赋值运算符隐藏(参见下面的注释)。
(13.5.3 Assignment) An assignment operator shall be implemented by a non-static member function with exactly one parameter. Because a copy assignment operator
operator=
is implicitly declared for a a class if not declared by the user, a base class assignment operator is always hidden by the copy assignment operator of the derived class.
(13.5.3 赋值) 赋值运算符应由一个只有一个参数的非静态成员函数实现。由于
operator=
如果用户未声明,则为类隐式声明了复制赋值运算符,因此基类赋值运算符始终被派生类的复制赋值运算符隐藏。
You can implement a dummy assignment operator which simply forwards the call to the base class operator=
, like this:
您可以实现一个虚拟赋值运算符,它只是将调用转发到基类operator=
,如下所示:
// Derived class
template<typename T, unsigned int N> class Derived : public Base<Derived, T, N>
{
public:
template<typename T0, class = typename std::enable_if<std::is_convertible<T0, T>::value>::type>
inline Derived& operator=(const T0& rhs)
{
return Base<Derived, T, N>::operator=(rhs);
}
};
回答by James Kanze
The assignment operator isinherited, sort of, but... In any given class, if you do not provide a copy assignment operator, the compiler generates one for you. That means that your derived classes effectively have an assignment operator:
赋值运算符是继承的,有点,但是......在任何给定的类中,如果您不提供复制赋值运算符,编译器会为您生成一个。这意味着您的派生类实际上有一个赋值运算符:
Derived& operator=( Derived const& );
And the usual hiding rules apply; this hides all of the base class assignment operators. (If the base class had an assignment operator with this signature, the derived class would inherit it normally.)
通常的隐藏规则适用;这隐藏了所有基类赋值运算符。(如果基类有一个带有此签名的赋值运算符,则派生类将正常继承它。)
回答by Mark B
Your assignment operator is technically inherited, but then it's hidden by the default copy assignment operator in the derived class. This default copy assignment then tries to call the base class's copy assignment which doesn't exist since you hid it with your own assignment.
The sanest way to resolve this is to not use operator overloading in non-obvious ways (
=
not meaning copy assignment for example). In this case, don't useoperator=
: Call it something likeassign
orset
and then it will inherit and not be hidden by the child copy assignment.These operators are inherited and there are no compiler versions so they will never be automatically hidden like
operator=
.It really is only constructors that aren't inherited, and I can't think of any other compiler-generated functions that could hide something from the parent as in
operator=
.
您的赋值运算符在技术上是继承的,但随后它被派生类中的默认复制赋值运算符隐藏。此默认副本分配然后尝试调用基类的副本分配,该副本分配不存在,因为您使用自己的分配隐藏了它。
解决这个问题的最明智的方法是不要以不明显的方式使用运算符重载(
=
例如,不是指复制赋值)。在这种情况下,不要使用operator=
: 将其命名为assign
orset
,然后它将继承并且不会被子副本分配隐藏。这些运算符是继承的,并且没有编译器版本,因此它们永远不会像
operator=
.它实际上只是未继承的构造函数,我想不出任何其他编译器生成的函数可以像
operator=
.