头文件声明规则:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #ifndef __COMPLEX__ #define __COMPLEX__
#include <cmath.h>
class ostream; class complex;
complex& __doapl (complex* ths, const complex& r);
class complex { public: complex (double r=0, double i=0): re(r), im(i) {} comple& operator += (const complex&); double real () const {return re;} double imag () const {return im;} private: double re, im;
friend complex& __doapl (complex*, const complex&); };
complex::function ... #endif
|
模板类:如complex
类中的re
与im
为double变量,如果要改为float或是int需要重新写一个新的类,而这个类仅改变re
和im
的变量类型,这里我们就可以写一个模板类,在类初始化的时候指定变量的类型:
1 2 3 4 5 6 7 8 9 10 11 12
| template<typename T> class complex { public: complex (T r=0, T i=0): re(r), im(i) {} comple& operator += (const complex&); T real () const {return re;} T imag () const {return im;} private: T re, im;
friend complex& __doapl (complex*, const complex&); }
|
1 2 3
| complex<double> c1(2.5, 1.5); complex<int> c2(2, 6);
|
inline函数(内联函数):函数如果在类本体里面定义,则叫做内联函数,如complex类里面的real
和imag
两个函数。这种函数比较快。
构造函数:创建对象时构造函数会被自动调用,构造函数没有返回值,其中re
和im
为初始化列,比在{}中赋值更加高效,在{}中赋值会包含两步,即初始化然后赋值,这样效率会低一点。
1 2 3 4 5
| { complex c1(2, 1); complex c2; complex* p = new complex(4); }
|
重载:析构函数可以有很多个,可以名字相同,但是在编译中函数名其实不相同。函数重载常常发生在构造函数之中。
如果一个构造函数已经有默认值,在其他构造函数中不能存在没有参数的情况,因为程序会不知道要调用哪个构造函数:
1 2 3 4 5 6 7 8 9 10 11 12 13
| class complex { public: complex (double r=0, double i=0): re(r), im(i) {} complex (): re(0), im(0) {} comple& operator += (const complex&); double real () const {return re;} double imag () const {return im;} private: double re, im;
friend complex& __doapl (complex*, const complex&); };
|
构造函数如果放在private中时的情况:Singleton设计模式,仅能创建一个实例。
析构函数:TODO
在class里面的函数有需要改变数据的内容的和不需要改变数据的内容的,如果这个函数不改变数据,则应该在后面加上const
,如下面的代码所示:
1
| double real () const {return re;}
|
参数传递:
- 传实例:如果变量大小很小,可以选择传值;
- 传引用:引用在低层就相当于指针,这种参数传递方式更佳;但是这种方法在函数中如果改变数据的话原值也会改变,如果想要其不改变的话,可以在参数前面加上
const
。
返回值:返回值传递
friend(友元):对于友元的函数,可以访问我们类中的数据(包括private中的数据);
同一个class的各个object互为友元;
什么情况下不能返回引用?返回在函数中创建的变量,变量在函数运行完之后内存会释放,故无法传递引用。
操作符重载:在c++中操作符就是一个函数,可以重新定义,即操作符重载;
第一种写法是写成一个成员函数:
1 2 3
| complex::operator += (const complex& r) { return __doapl (this, r); }
|
this
:所有成员函数均有一个this参数,谁调用这个函数,谁就是this,this为一个指针;
第二种写法是非成员函数的写法:这种方法没有使用this指针,这种函数只能是全局函数。
1 2 3 4 5 6 7 8 9 10
| 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)); }
|
1 2 3 4 5 6 7
| { complex c1(2,1); complex c2; c2 = c1 + c2; c2 = c1 + 5; }
|
临时对象:用法
总结:
1 2 3 4 5 6 7 8 9 10 11
| class complex { public: complex (double r=0, double i=0): re(r), im(i) {} comple& operator += (const complex&); double real () const {return re;} double imag () const {return im;} private: double re, im;
friend complex& __doapl (complex*, const complex&); };
|
从头写一个复数类:
头文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| #ifndef __COMPLEX__ #define __COMPLEX__ class complex { public: complex (double r = 0, double i = 0): re(0), im(0) {}; 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 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)); } #include<iostream.h> inline ostream& operator << (ostream& os, const complex& x) { return cout << '(' << real(x) << ',' << imag(x) << ')' << endl; }
operator + #endif
|