在基 Class 中重载赋值运算符
Overloading Assignment Operator in Base Class
我有一个名为 BaseSignal
、
的模板 class
template <class T>
class BaseSignal
{
public:
// Constructor
BaseSignal(long buf_size, bool is_async, SimData *sim)
....
从这个 class 派生出另外两个模板化的 classes,Net
和 Reg
。 (对于那些感兴趣的人,我正在对 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
.
也类似
在基础 class 中,我将 Set
和 Get
方法定义为虚拟方法,
// 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 {};
因为 Net
和 Reg
对这些有不同的行为。所以这是有趣的部分。
+= 基地超载工程Class
在基础 class 中,我定义了这个运算符来调用虚拟 Set
和 Get
操作,这按预期工作。
在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_real
和 net_int
,当我这样做时
*net_real += 1.1;
*net_int += 1l;
净值正确递增。这是奇怪的部分
= 重载在基础中不起作用 Class
在 Net
class 中重载 =
工作正常,正如预期的那样:
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;
}
我可以很好地编译 class 文件,但是当我编译 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>&&'
我不是 100% 确定我理解 "candidate" 部分。它是否试图调用复制构造函数?而且我也不明白为什么没有与操作数 (operand types are 'cpysim::Net<double>' and 'double')
的匹配,因为 Net
是从 BaseSignal
派生的,并且我已经为这些操作数定义了运算符。更令人费解的是为什么它适用于 +=
而不是 =
.
这是一个name-hiding问题;派生的 class 具有 implicitly-generated operator=
,包括 copy assignment operator and move assignment operator,其中 隐藏 基数的 operator=
class.
这就是 name lookup 的工作原理。当在派生 class 作用域中找到名称 operator=
时,将不会检查包括基础 class 作用域在内的进一步作用域,名称查找将停止。然后根据找到的名称进行重载解析,最后导致编译错误。
operator+=
没有这个问题;在派生的 class.
中没有(隐式或显式)声明 operator+=
您可以使用 using
将基础 class 的 operator=
引入派生的 class 范围。例如
template <class T>
class Net : public BaseSignal<T>
{
public:
using BaseSignal<T>::operator=;
...
};
我有一个名为 BaseSignal
、
template <class T>
class BaseSignal
{
public:
// Constructor
BaseSignal(long buf_size, bool is_async, SimData *sim)
....
从这个 class 派生出另外两个模板化的 classes,Net
和 Reg
。 (对于那些感兴趣的人,我正在对 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
.
在基础 class 中,我将 Set
和 Get
方法定义为虚拟方法,
// 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 {};
因为 Net
和 Reg
对这些有不同的行为。所以这是有趣的部分。
+= 基地超载工程Class
在基础 class 中,我定义了这个运算符来调用虚拟 Set
和 Get
操作,这按预期工作。
在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_real
和 net_int
,当我这样做时
*net_real += 1.1;
*net_int += 1l;
净值正确递增。这是奇怪的部分
= 重载在基础中不起作用 Class
在 Net
class 中重载 =
工作正常,正如预期的那样:
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;
}
我可以很好地编译 class 文件,但是当我编译 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>&&'
我不是 100% 确定我理解 "candidate" 部分。它是否试图调用复制构造函数?而且我也不明白为什么没有与操作数 (operand types are 'cpysim::Net<double>' and 'double')
的匹配,因为 Net
是从 BaseSignal
派生的,并且我已经为这些操作数定义了运算符。更令人费解的是为什么它适用于 +=
而不是 =
.
这是一个name-hiding问题;派生的 class 具有 implicitly-generated operator=
,包括 copy assignment operator and move assignment operator,其中 隐藏 基数的 operator=
class.
这就是 name lookup 的工作原理。当在派生 class 作用域中找到名称 operator=
时,将不会检查包括基础 class 作用域在内的进一步作用域,名称查找将停止。然后根据找到的名称进行重载解析,最后导致编译错误。
operator+=
没有这个问题;在派生的 class.
operator+=
您可以使用 using
将基础 class 的 operator=
引入派生的 class 范围。例如
template <class T>
class Net : public BaseSignal<T>
{
public:
using BaseSignal<T>::operator=;
...
};