c++ - 在基类中重载赋值运算符

标签 c++ operator-overloading name-lookup

我有一个名为 BaseSignal 的模板类,

  template <class T>
  class BaseSignal
  {
    public:
    // Constructor
    BaseSignal(long buf_size, bool is_async, SimData *sim)
    ....

从该类派生出另外两个模板类: NetReg 。 (对于那些感兴趣的人,我正在 Verilog 中对并发和顺序分配的行为进行建模)。这些定义为

  template <class T>
  class Net : public BaseSignal<T>
  {
    public:
    Net(long buf_size, bool is_async, SimData* sim)
      : BaseSignal<T>(buf_size, is_async, sim) {};
      ....

Reg 也类似。

在基类中,我将 SetGet 方法定义为 virtual,

    // Virtual settors
    virtual void Set(long val) {};
    virtual void Set(double val) {};

    // Virtual gettors
    virtual void Get(long* val) const {};
    virtual void Get(double* val) const {};

因为 NetReg 对于这些有不同的行为。这是有趣的部分。

+= 基类中的重载工作

在基类中,我定义此运算符来调用虚拟 SetGet 操作,它按预期工作。

BaseSignal 中:

    BaseSignal<T>& operator+=(const double& rhs)
    {
      T rval;
      this->Get(&rval);
      this->Set(rval + static_cast<T>(rhs));
      return *this;
    }
    BaseSignal<T>& operator+=(const long& rhs)
    {
      T rval;
      this->Get(&rval);
      this->Set(rval + static_cast<T>(rhs));
      return *this;
    }

在我的代码中,我有指针 net_realnet_int 以及当我这样做时

  *net_real += 1.1;
  *net_int += 1l;

净值正确增加。这是奇怪的部分

= 重载在基类中不起作用

= 类中重载 Net 工作正常,正如预期的那样:

    Net<T>& operator=(const double& rhs)
    {
      this->Set(static_cast<T>(rhs));
      return *this;
    }
    Net<T>& operator=(const long& rhs)
    {
      this->Set(static_cast<T>(rhs));
      return *this;
    }

但是如果我把它放在 BaseSignal 中,

    BaseSignal<T>& operator=(const double& rhs)
    {
      this->Set(static_cast<T>(rhs));
      return *this;
    }
    BaseSignal<T>& operator=(const long& rhs)
    {
      this->Set(static_cast<T>(rhs));
      return *this;
    }

我可以很好地编译类文件,但是当我编译 main.cpp 时,我得到这个:

ctests/main.cpp: In function 'int main()':
ctests/main.cpp:28:15: error: no match for 'operator=' (operand types are 'cpysim::Net<double>' and 'double')
   28 |   *net_real = 1.0;
      |               ^~~
In file included from ctests/main.cpp:9:
csrc/signals_nets.hpp:456:9: note: candidate: 'constexpr cpysim::Net<double>& cpysim::Net<double>::operator=(const cpysim::Net<double>&)'
  456 |   class Net : public BaseSignal<T>
      |         ^~~
csrc/signals_nets.hpp:456:9: note:   no known conversion for argument 1 from 'double' to 'const cpysim::Net<double>&'
csrc/signals_nets.hpp:456:9: note: candidate: 'constexpr cpysim::Net<double>& cpysim::Net<double>::operator=(cpysim::Net<double>&&)'
csrc/signals_nets.hpp:456:9: note:   no known conversion for argument 1 from 'double' to 'cpysim::Net<double>&&'

我不确定我是否理解“候选人”部分。它是否试图调用复制构造函数?而且我也不明白为什么与操作数 (operand types are 'cpysim::Net<double>' and 'double') 不匹配,因为 Net 是从 BaseSignal 派生的,并且我已经为这些操作数定义了运算符。更令人困惑的是为什么它适用于 += 而不是 =

最佳答案

这是一个名称隐藏问题;派生类具有隐式生成的operator=,包括 copy assignment operatormove assignment operator ,它隐藏基类的operator=

就是这样name lookup作品。当在派生类作用域中找到名称 operator= 时,将不会检查包括基类作用域在内的进一步作用域,名称查找将停止。之后根据找到的名称进行重载解析,最终导致编译错误。

operator+= 没有这样的问题;派生类中没有(隐式或显式)声明 operator+=

您可以使用using将基类的operator=引入到派生类作用域中。例如

template <class T>
class Net : public BaseSignal<T>
{
  public:
    using BaseSignal<T>::operator=;
  ...
};

关于c++ - 在基类中重载赋值运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56728781/

相关文章:

c++ - STLpriority_queue实例化的疑问

c++ - opencv中的BMP不是无损的吗?

python - 在 Python 中为表达式定义新的语义

c++ - 如何在没有 dynamic_cast 的派生类型上实现 "less"?

c++ - 赋值运算符重载c++的返回值

c++ - 如何将权限级别从 Linux 上的 C++ 程序提升到 root

c++ - 在统一内存 CUDA C/C++ 中分配一个二维 vector

c++ - 什么是 “Argument-Dependent Lookup”(又名ADL或 “Koenig Lookup”)?

c++ - 重载的子类函数不能调用相似名称的父类

c++ - 为什么命名空间中的函数看不到我全局定义的 operator<<?