C++基础--complex(复数)类的设计过程与思考总结
项目
1.设计complex(复数类)
需求:1)实部,虚部re,im
2)重写+=符号,调用friend_doapl函数,对两个复数进行相加 其中+=函数调用一个全局函数_doapl(complex*,complext&)进行处理。这里只用完成两个复数的相加
3)重写+符号,这里只用完成两个复数,复数和实数的相加
设计完成后的代码
#ifndef __MYCOMPLEX__#define __MYCOMPLEX__
class complex;
complex&
__doapl(complex* ths, const complex& r);
complex&
__doami(complex* ths, const complex& r);
complex&
__doaml(complex* ths, const complex& r);
class complex
{
public:
complex(double r = 0, double i = 0) : re(r), im(i) { }
complex& operator += (const complex&);
double real() const { return re; }
double imag() const { return im; }
private:
double re, im;
friend complex& __doapl(complex*, const complex&);
};
inline complex&
__doapl(complex* ths, const complex& r)
{
ths->re += r.re;
ths->im += r.im;
return *ths;
}
inline complex&
complex::operator += (const complex& r)
{
return __doapl(this, r);
}
inline double
imag(const complex& x)
{
return x.imag();
}
inline double
real(const complex& x)
{
return x.real();
}
inline complex
operator + (const complex& x, const complex& y)
{
return complex(real(x) + real(y), imag(x) + imag(y));
}
inline complex
operator + (const complex& x, double y)
{
return complex(real(x) + y, imag(x));
}
inline complex
operator + (double x, const complex& y)
{
return complex(x + real(y), imag(y));
}
endif //MYCOMPLEX
设计:
1)确定成员变量以及get方法 思考函数const,real()和img需要加,因为不需要修改值。
2)确定重载符号operator +=方法。
complex& operator +=(const complex&);
思考返回值是什么类型。我们在复数类计算时,经常 x+=y,等价于x = x+y. 因此,确定返回的是原来的x的值,也就是this。我们可以得出,直接传回引用,因为我们传回去得并不是local variable。但为什么我们不设计是void类型呢?因为当我们计算x+=y的时候,我们可以直接通过引用改变x的值呀?
就比如:
complex& operator +=(const complex& c){this.re = this.re+c.real();
}
原因就在于,在c++中可以连续复制,如 x1+=x2+=x3; 当发生这种情况的时候,引用必须返回以供作为右值以供下一次的运算。
思考形式参数。能用引用得就用引用。且原值能不能修改呢? x = x+y this指的是x的数据,形式参数指的是y的数据。x的数据发生了改变,但是y的没有。所以我们得出,形式参数要加上const。
3)全局函数_doapl(complex&,complext&)
可能是因为其他地方也要用到,所以就把它写成了全局函数而不是成员函数。为了实现 operator+=调用它,我们得将它声明为一个友元。
其成员变量两个一个是complex*而非complex&的原因是,要传入this,与operator+=发生联动。
4)设计 operator+重载
思考返回值类型,假设有 x3 = x1+x2。x3必然是在函数内新建一个变量并返回,所以不能返回一个局部变量的引用。只能使用值传递。
此外,我们可以注意到,operator+定义在了类外,因为它不需要this这个变量,且operator+二目运算符只允许有两个参数,要想不加入this(类内函数默认添加this形式参数),只能写在类外作为成员函数。
那还有几个问题,复数相加有很多种可能,以下是应该考虑的可能性,我们必须根据这些可能性设计函数的重载:
/**有三种情况
1.复数加复数
2.复数+double
3.double+复数
**/
inline complex
operator + (const complex& x, const complex& y)
{
return complex (real (x) + real (y), imag (x) + imag (y));
}
inline complex
operator + (const complex& x, double y)
{
return complex (real (x) + y, imag (x));
}
inline complex
operator + (double x, const complex& y)
{
return complex (x + real (y), imag (y));
}
从complex得到的经验
1)若方法不需要修改数据,一定加上const,因为const对象只能调用const方法。若方法不加const,const对象功能不全。
- 形式参数都应该传递引用,如果不需要修改,则一定加上const,否则原值可能被修改。若直接传递了值,则发生复制,会很慢。当然,char这种一个字节的参数可以传值。
3)返回值也尽量用引用传递,快。但是一定不能返回局部变量的引用,因为局部变量存在栈中,方法执行完之后内存就被回收了。
4)简单的函数要加inline即使编译器会自动选择。
5).h文件的划分
其中,类声明里的函数不用写具体的形式参数,只用写形式参数的类型即可。简单的函数可以在类声明部分就定义如 real()和Img()。复杂的应该在函数体外进行定义。最后,类内的函数均会自动加上inline,在类外定义的函数若比较简单,应该手动建议编译器使用inlien.
6)操作符重载时,若是双目运算符 如 + 则应该定义为全局函数。
如z = x+y。使用+号时,不需要this的值。
与之相对的是单目运算符,如==或+=
如判断 z==y 的时候,我们需要用到z的值,所以必须定义在类内,所以就没有意义了
7)在函数声明阶段,复杂的函数不用写函数体,也不用写具体的形式参数,只用写形式参数的类型。
如:
complex&operator +=(const complex&); //不需要写成(const complex&r)
,只写函数名。
但简单的如real()可以写完函数体。复杂的函数应该在类定义区域完成函数体的编写。
以上是 C++基础--complex(复数)类的设计过程与思考总结 的全部内容, 来源链接: utcz.com/a/72696.html