Vin*_*ent 36 c++ inheritance operator-overloading crtp
在我刚刚进行的测试之前,我相信只有构造函数不会在C++中继承.但显然,任务operator=不是......
operator+=,operator-=...?事实上,我在做一些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>
{
};
Run Code Online (Sandbox Code Playgroud)
是否有任何解决方案可以使其工作?
编辑:好的,我已经解决了这个问题.为什么以下不起作用?如何解决问题?
#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;
}
Run Code Online (Sandbox Code Playgroud)
eq-*_*eq- 35
赋值运算符在技术上是继承的; 但是,它始终由派生类的显式或隐式定义的赋值运算符隐藏(请参阅下面的注释).
(13.5.3赋值)赋值运算符应由具有一个参数的非静态成员函数实现.因为
operator=如果未由用户声明,则为aa类隐式声明复制赋值运算符,则基类赋值运算符始终由派生类的复制赋值运算符隐藏.
您可以实现一个伪赋值运算符,它只是将调用转发给基类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);
}
};
Run Code Online (Sandbox Code Playgroud)
Jam*_*nze 10
赋值运算符是继承的,排序,但是......在任何给定的类中,如果您不提供复制赋值运算符,编译器会为您生成一个.这意味着派生类有效地具有赋值运算符:
Derived& operator=( Derived const& );
Run Code Online (Sandbox Code Playgroud)
通常的隐藏规则适用; 这隐藏了所有基类赋值运算符.(如果基类具有带此签名的赋值运算符,则派生类将正常继承它.)
您的赋值运算符在技术上是继承的,但它被派生类中的默认复制赋值运算符隐藏.然后,此默认复制分配尝试调用基类的复制分配,该分配不存在,因为您使用自己的分配隐藏它.
解决这个问题的最好方法是不以非显而易见的方式使用运算符重载(=例如,不是指复制赋值).在这种情况下,请不要使用operator=:将其assign称为或类似于set然后它将继承并且不会被子复制赋值隐藏.
这些运算符是继承的,没有编译器版本,因此它们永远不会被自动隐藏operator=.
它实际上只是没有继承的构造函数,我想不出任何其他编译器生成的函数可以隐藏父类中的内容operator=.
| 归档时间: |
|
| 查看次数: |
21921 次 |
| 最近记录: |