代码之家  ›  专栏  ›  技术社区  ›  haster8558

过载问题

  •  3
  • haster8558  · 技术社区  · 7 年前

    我试图创建一组类来处理复数。我已经看到有一组用于复数的类,但因为我正在学习C++,所以我认为创建一个基本实现是一个好主意。当我试图使运算符“/”过载时,出现了问题。我遇到了一个segfault,我无法理解问题是否在于我对部门的执行:

    复杂的水电站:

    #include <iostream>
    #include <cstdlib>
    
    class Complex {
      float real;
      float imm;
    public:
      Complex(float new_real = 0,float new_imm = 0) {this->real = new_real;this->imm = new_imm;}
      void set(float new_real,float new_imm) {this->real = new_real; this->imm = new_imm;}
      float get_real(void) const { return this->real;}
      float get_imm(void) const { return this->imm;}
      Complex conj(void) const {Complex tmp; tmp.set(this->real,-1.0 * this->imm); return tmp;}
      friend std::ostream& operator<<(std::ostream& os, const Complex& cpx) {os << "Real: " << cpx.real << " Imm: " << cpx.imm << std::endl; return os; }
      friend Complex operator*(const Complex& lhs,const Complex& rhs);
      friend Complex operator+(const Complex& lhs,const Complex& rhs);
      friend Complex operator+(const Complex& lhs,const float& rhs);
    };
    

    复杂的cpp:

    #include "complex.hpp"
    
    
    Complex operator*(const Complex& lhs,const Complex& rhs)
    {
      float real_part = (lhs.real * rhs.real) - ( lhs.imm * rhs.imm);
      float imm_part = (lhs.real * rhs.imm) + ( lhs.imm * rhs.real);
      Complex result;
      result.set(real_part,imm_part);
      return result;
    }
    
    Complex operator+(const Complex& lhs,const Complex& rhs)
    {
      float real_part = lhs.real + rhs.real;
      float imm_part = lhs.imm + rhs.imm;
      Complex result;
      result.set(real_part,imm_part);
      return result;
    }
    
    Complex operator+(const Complex& lhs,const float& rhs)
    {
      float real_part = lhs.real + rhs;
      float imm_part = lhs.imm;
      Complex result;
      result.set(real_part,imm_part);
      return result;
    }
    
    Complex operator/(const Complex& lhs,const Complex& rhs)
    {
      Complex numerator(0,0);
      numerator = rhs * rhs.conj();
    
      Complex denominator(0,0);
      denominator = lhs * rhs.conj();
    
      Complex result;
      float real_numerator = numerator.get_real();
      result = denominator / real_numerator;
      return result;
    }
    
    Complex operator/(const Complex& lhs,const float& rhs)
    {
      float real_part = lhs.get_real() / rhs;
      float imm_part = lhs.get_imm() / rhs;
      Complex result;
      result.set(real_part,imm_part);
      return result;
    }
    

    2复数除法的全部思想是将分子共轭的分子和分母相乘,以便分子上只有一个实数。我想说清楚:

    (a+ib)/(c+id)=((a+ib)/(c+id))*((c-id)/(c-id))=((a+ib)*(c-id))/(c^2+d^2)

    现在,当我尝试这样做时:

    主要的cpp:

    int main(int argc, char *argv[])
    {
      Complex x(4,8);
      Complex y(3,7);
      Complex result = x / y;
      result = x / 6;
      return 0;
    }
    

    我有一个错误,我不明白:

    (gdb) break main
    Breakpoint 2 at 0x401c56: file equalization_main.cpp, line 49.
    (gdb) r
    The program being debugged has been started already.
    Start it from the beginning? (y or n) y
    `/home/campiets/workspace/frontend/dfe_equalizer_fe/dev/view/src_c/test' has changed; re-reading symbols.
    Starting program: /home/campiets/workspace/frontend/dfe_equalizer_fe/dev/view/src_c/test 
    
    Breakpoint 2, main (argc=1, argv=0x7fffffffbf08) at equalization_main.cpp:49
    49    Complex x(4,8);
    (gdb) n
    50    Complex y(3,7);
    (gdb) n
    51    Complex result = x / y;
    (gdb) n
    
    Program received signal SIGSEGV, Segmentation fault.
    0x0000000000401e64 in Complex::Complex (this=<error reading variable: Cannot access memory at address 0x7fffff3feff8>, new_real=<error reading variable: Cannot access memory at address 0x7fffff3feff4>, 
        new_imm=<error reading variable: Cannot access memory at address 0x7fffff3feff0>) at complex.hpp:38
    38    Complex(float new_real = 0,float new_imm = 0) {this->real = new_real; this->imm = new_imm;}
    

    有什么想法吗?

    2 回复  |  直到 7 年前
        1
  •  5
  •   Sid S    7 年前
    Complex operator/(const Complex& lhs,const Complex& rhs)
    {
      ...
      Complex denominator...;
      ...
      float real_numerator = ...;
      result = denominator / real_numerator;
      ...
    }
    

    这是无限递归。

    因为编译器没有看到 operator/(const Complex &lhs, const float &rhs) ,它转换 float 参数到 Complex 因此得到递归。

    最简单的解决方案是声明或定义 操作员/(const Complex和lhs、const float和rhs) 之前 operator/(const Complex &lhs, const Complex &rhs) .

    不过,我倾向于将操作符实现为类成员。这会产生更简单的源代码,也解决了问题。

        2
  •  3
  •   R Sahu    7 年前

    功能

    Complex operator/(const Complex& lhs,const Complex& rhs) { ... }
    

    导致堆栈溢出,因为行

    result = denominator / real_numerator;
    

    最终被解释为:

    result = denominator / Complex(real_numerator);
    

    您可以通过定义或声明

    Complex operator/(const Complex& lhs, const float& rhs)
    

    在它之前。

    如果更改代码以使用:

    Complex operator/(const Complex& lhs,const float& rhs)
    {
       return Complex(lhs.get_real()/rhs, lhs.get_imm()/rhs);
    }
    
    Complex operator/(const Complex& lhs,const Complex& rhs)
    {
       ...
    }
    

    您的程序将正常工作。


    简化上述内容的建议 operator/ 作用

    如果添加以下成员函数

    float magnitude_square() const { return (real*real + imm*imm); }
    

    然后您可以使用

    Complex operator/(const Complex& lhs,const Complex& rhs)
    {
       return (lhs * rhs.conj())/rhs.magnitude_square());
    }