C++面向对象高级开发-Complex复数类的设计与实现
Notes
C++类分为:
- Object Based(基于对象)
- Object Oriented(面向对象)
基于对象:
- 不带有指针成员的类:Complex
- 带有指针成员的类:String
面对单一class的设计: 面向对象:
- 继承(inheritance)
- 复合(composition)
- 委托(delegation)
面对多重class的设计:
- 类与类之间的关系
设计规范
设计规范1:
函数在类体内定义完成,自动成为inline内联函数候选人 数据要放在private区
设计规范2:
防卫式(guard)声明
#ifndef __COMPLEX__
#define __COMPLEX__
……
#endif
设计规范3:
构造函数:
class complex {
public:
complex (double r = 0, double i = 0) : re (r), im (i) {} //初值列
...
private:
double re, im;
...
}
若增加构造函数:
complex() : re(0), im(0) {}
是不允许的,原因:默认的构造函数有默认初值。 Singleton模式:不允许被外界创建对象时,构造函数放在private区。
设计规范4:
若该函数内容不会改变,增加const关键字
double real() const { return re; }
double imag() const { return im; }
设计规范5:
参数传递引用优先。若需保持引用对象不变,可增加const关键字。
complex& operator += (const complex&);
返回值传递同理。
设计规范6:
相同class的对象互为友元。 如:
class complex {
public:
int func(const complex& param) {
return param.re + param.im;
}
private:
double re, im;
};
int main(int argc, const char *argv[]) {
complex c1(2,1);
complex c2;
c2.func(c1);
}
设计规范7:
- 所有的成员函数都带有隐含参数this,this指调用者。
- 传递者无需知道接收者是以reference形式接收
inline complex& __doapl(complex* ths, const complex& r) {
...
return *ths; // *ths为传递者 inline complex&中,complex&为接收者
}
inline complex& complex::operator += (const complex& r) {
return __doapl(this,r);
}
complex c1(2,1);
complex c2(5);
complex c3;
c2+=c1;
c3+=c2+=c1;
考虑到
c3+=c2+=c1
的表达式中,c2+=c1
运算的结果必须为complex&
才可继续与c3运算,所以,inline complex& complex::operator +=
的返回值类型必须为complex&
,而不可为void
。
- 所有非成员函数都不含有隐含参数this。
inline complex operator + (const complex& x, const complex& y) {
return complex(x.real()+y.real(), x.imag()+y.imag());
}
如上述非成员函数示例中,返回值为函数内创建,即为Local Object,函数执行结束,返回值被释放。所以,绝对不可以使用引用传递返回值,只能按值传递。如
complex();
为临时对象,生命周期只有当前行,当前行执行完毕,生命周期结束。
总结
总结:编写程序思考的步骤:
- 防卫式声明
- 设计复数类,考虑实部虚部数据放在私有private区。
- 对数据进行操作的函数。首先为无返回类型的构造函数,考虑参数默认值,考虑参数按值传递还是按引用传递。构造函数要使用初值列赋初值。
- 考虑设计为成员函数或非成员函数。成员函数写在class中。考虑参数传递和返回值类型。
- 设计函数时是否要加const。不改动数据加const。class内部函数为inline候选人。
- 非Local object返回值类型传引用。
- 如
operator +
设计为成员函数,功能受限。由于成员函数的操作符作用在左值,如对操作符<<
重载时,使用写法应为c1 << cout;
,有违于常规写法,所以此函数设计应考虑全局操作符重载。
Complex函数完整源码
Complex-Test.cpp
//
// main.cpp
// Complex
//
// Created by Fa1c0n on 2020/2/17.
// Copyright © 2020 Fa1c0n. All rights reserved.
//
#include <cstdlib>
#include "Complex.h"
using namespace std;
int main(int argc, const char * argv[]) {
Complex c1(2, 1);
Complex c2(4, 0);
cout << c1 << endl;
cout << c2 << endl;
cout << c1+c2 << endl;
cout << c1-c2 << endl;
cout << c1*c2 << endl;
cout << c1 / 2 << endl;
cout << (c2 - 2) << endl;
cout << (5 + c2) << endl;
cout << conj(c1) << endl;
cout << norm(c1) << endl;
cout << polar(10, 4) << endl;
cout << (c1 += c2) << endl;
cout << (c1 -= c2) << endl;
cout << (c1 *= c2) << endl;
cout << (c1 /= c2) << endl;
cout << (c1 == c2) << endl;
cout << (c1 != c2) << endl;
cout << (c1 == 2) << endl;
cout << (c2 != 4) << endl;
cout << +c2 << endl;
cout << -c2 << endl;
return EXIT_SUCCESS;
}
Complex.hpp
//
// Complex.h
// Complex
//
// Created by Fa1c0n on 2020/2/17.
// Copyright © 2020 Fa1c0n. All rights reserved.
//
#ifndef __COMPLEX_H__
#define __COMPLEX_H__
#include <iostream>
#include <cmath>
using namespace std;
class Complex;
Complex& __doapl(Complex& ths, const Complex& comp);
Complex& __doami(Complex& ths, const Complex& comp);
Complex& __doaml(Complex& ths, const Complex& comp);
Complex& __doadi(Complex& ths, const Complex& comp);
class Complex {
public:
Complex(double real = 0, double imag = 0) : re(real), im(imag) {};
double real() const {return re;}
double imag() const {return im;}
Complex& operator += (const Complex&);
Complex& operator -= (const Complex&);
Complex& operator *= (const Complex&);
Complex& operator /= (const Complex&);
private:
double re, im;
friend Complex& __doapl(Complex*, const Complex&);
friend Complex& __doami(Complex*, const Complex&);
friend Complex& __doaml(Complex*, const Complex&);
friend Complex& __doadi(Complex*, const Complex&);
};
inline ostream& operator << (ostream& os, const Complex& comp) {
return os << "[" << comp.real() << ", " << comp.imag() << "]";
}
inline double real (const Complex& x) {
return x.real();
}
inline double imag (const Complex& x) {
return x.imag();
}
inline Complex operator + (const Complex& x) {
return x;
}
inline Complex operator - (const Complex& x) {
return Complex(-x.real(), -x.imag());
}
inline Complex operator + (const Complex& x, const Complex& y) {
return Complex(x.real()+y.real(), x.imag()+y.imag());
}
inline Complex operator + (const double x, const Complex& y) {
return Complex(x+y.real(), y.imag());
}
inline Complex operator + (const Complex& x, const double y) {
return Complex(x.real()+y, x.imag());
}
inline Complex operator - (const Complex& x, const Complex& y) {
return Complex(x.real()-y.real(), x.imag()-y.imag());
}
inline Complex operator - (const double x, const Complex& y) {
return Complex(x-y.real(), y.imag());
}
inline Complex operator - (const Complex& x, const double y) {
return Complex(x.real()-y, x.imag());
}
inline Complex operator * (const Complex& x, const Complex& y) {
return Complex(x.real()*y.real(), x.imag()*y.imag());
}
inline Complex operator * (const double x, const Complex& y) {
return Complex(x*y.real(), y.imag());
}
inline Complex operator * (const Complex& x, const double y) {
return Complex(x.real()*y, x.imag());
}
inline Complex operator / (const Complex& x, const Complex& y) {
return Complex(x.real()/y.real(), x.imag()/y.imag());
}
inline Complex operator / (const Complex& x, const double y) {
return Complex(x.real()/y, x.imag());
}
inline Complex operator / (const double x, const Complex& y) {
return Complex(x/y.real(), y.imag());
}
inline Complex& __doapl(Complex* ths, const Complex& comp) {
ths->re += comp.re;
ths->im += comp.im;
return *ths;
}
inline Complex& Complex::operator += (const Complex& comp) {
return __doapl(this, comp);
}
inline Complex& __doami(Complex* ths, const Complex& comp) {
ths->re -= comp.re;
ths->im -= comp.im;
return *ths;
}
inline Complex& Complex::operator -= (const Complex& comp) {
return __doami(this, comp);
}
inline Complex& __doaml(Complex* ths, const Complex& comp) {
ths->re *= comp.re;
ths->im *= comp.im;
return *ths;
}
inline Complex& Complex::operator *= (const Complex& comp) {
return __doaml(this, comp);
}
inline Complex& __doadi(Complex* ths, const Complex& comp) {
if (comp.re != 0 && comp.im != 0) {
ths->re /= comp.re;
ths->im /= comp.im;
}
return *ths;
}
inline Complex& Complex::operator /= (const Complex& comp) {
return __doadi(this, comp);
}
inline bool operator == (const Complex& x, const Complex& y) {
return (x.real() == y.real()) && (x.imag() == y.imag());
}
inline bool operator == (const Complex& x, const double y) {
return (x.real() == y) && (x.imag() == 0);
}
inline bool operator == (const double x, const Complex& y) {
return (x == y.real()) && (y.imag() == 0);
}
inline bool operator != (const Complex& x, const Complex& y) {
return (x.real() != y.real()) || (x.imag() != y.imag());
}
inline bool operator != (const Complex& x, const double y) {
return (x.real() != y) || (x.imag() != 0);
}
inline bool operator != (const double x, const Complex& y) {
return (x != y.real()) || (y.imag() != 0);
}
inline Complex conj (const Complex& comp) {
return Complex(comp.real(), -comp.imag());
}
inline double norm (const Complex& comp) {
return comp.real()*comp.real()+comp.imag()*comp.imag();
}
inline Complex polar (const double r, const double t) {
return Complex(r*cos(t), r*sin(t));
}
#endif
/* Complex_h */