C++ 重载运算符返回派生类对象而不是基类

标签 c++ templates inheritance operator-overloading derived-class

假设我有一个模板类,我在其中重载了一个运算符,比方说乘法运算符:

template <typename T1>
class base_matrix{

  public:
  T1* M; 
  ....

  base_matrix<T1>& operator*=(const complex<double>& f){  
    for(int i=0;i<n_elts;i++) { M[i] *= (T1)f; }
    return *this;
  }

  friend base_matrix<T1> operator*(const int& f, const base_matrix<T1>& ob){
    base_matrix<T1> res(ob);  res *= f; return res;
  }
}

然后我用专门的模板参数定义了一个派生类:

class CMATRIX : public base_matrix< complex<double> >{

public:


}

在我的理解中,由于运算符是在派生类中继承的,因此可以创建一个 CMATRIX 类型的对象并将其乘以一个复数。我希望得到的是 CMATRIX 类型的另一个对象。我实际得到的是基类类型的对象(带有替换的模板参数) base_matrix< complex<double> > .这很清楚 - 派生对象调用基类方法,该方法返回基类对象。

当然,我可以在派生类中进行显式转换:

friend CMATRIX operator*(const CMATRIX& ob, const complex<double>& f){     
  return CMATRIX(ob * f);
}

但这似乎是对运算符重载的不必要的重新定义。也就是说 - 如果我需要在派生类中显式地重新定义所有运算符重载 - 在基类中定义它们有什么意义?

所以,这是我的问题之一。另一个更技术性的问题 - 如何让派生类运算符在没有显式转换的情况下返回正确的(派生)类?

最佳答案

不是一个很好的解决方案但是...

您可以在模板参数为派生类(CRTP 样式)的模板基类中插入 friend 运算符。

一个例子

#include <complex>
#include <type_traits>

template <typename T>
struct multM
 {
  friend T operator* (int const f, T const & ob)
   { T res(ob); res *= f; return res; }
 };

template <typename T1>
class base_matrix : public multM<base_matrix<T1>>
 {
   public:
      T1 *        M; 
      std::size_t n_elts;

      base_matrix<T1>& operator*=(const std::complex<double>& f){  
         for(int i=0;i<n_elts;i++) { M[i] *= (T1)f; }
         return *this;
      }
 };

class CMATRIX : public base_matrix<std::complex<double>>,
                public multM<CMATRIX>
 { };

int main()
 {
   static_assert(std::is_same<base_matrix<float>,
                    decltype(int{}*base_matrix<float>{})>::value, "!");
   static_assert(std::is_same<CMATRIX,
                    decltype(int{}*CMATRIX{})>::value, "!!");
 }

关于C++ 重载运算符返回派生类对象而不是基类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43698859/

相关文章:

c++ - C++ 新手,签名定义

c++ - 编译时类型名到函数名的映射

C++ 我可以根据给单个构造函数的参数创建派生类而不是 bass 类吗?

python - 如果子类中缺少 __init__() 会发生什么?

c++ - 嵌套模板类型的部分特化在 VC++ 2012 编译器中生成 "internal error"

c++ - 难以存储 QImage 然后恢复它

c++ - C++ 模板资源

asp.net-mvc - ASP.NET MVC ModelBinding 继承类

C++ 程序崩溃且没有错误

c++ - 编译器无法解析通过 std::mem_fn 传递的匹配类方法