[c++] 面向对象课程(一)-- 不带指针类的设计

时间:2021-07-29
本文章向大家介绍[c++] 面向对象课程(一)-- 不带指针类的设计,主要包括[c++] 面向对象课程(一)-- 不带指针类的设计使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

Object Based(基于对象)

  • class without pointer menbers
  • class with pointer menbers

Object Oriented(面向对象)

  • Classes之间的关系
    • 继承(inheritance)
    • 复合(composition)
    • 委托(delegation) 

complex类:

complex.h

  1 #ifndef __MYCOMPLEX__
  2 #define __MYCOMPLEX__
  3 
  4 class complex; 
  5 complex&
  6   __doapl (complex* ths, const complex& r);
  7 complex&
  8   __doami (complex* ths, const complex& r);
  9 complex&
 10   __doaml (complex* ths, const complex& r);
 11 
 12 
 13 class complex
 14 {
 15 public:
 16   complex (double r = 0, double i = 0): re (r), im (i) { }
 17   complex& operator += (const complex&);
 18   complex& operator -= (const complex&);
 19   complex& operator *= (const complex&);
 20   complex& operator /= (const complex&);
 21   double real () const { return re; }
 22   double imag () const { return im; }
 23 private:
 24   double re, im;
 25 
 26   friend complex& __doapl (complex *, const complex&);
 27   friend complex& __doami (complex *, const complex&);
 28   friend complex& __doaml (complex *, const complex&);
 29 };
 30 
 31 
 32 inline complex&
 33 __doapl (complex* ths, const complex& r)
 34 {
 35   ths->re += r.re;
 36   ths->im += r.im;
 37   return *ths;
 38 }
 39  
 40 inline complex&
 41 complex::operator += (const complex& r)
 42 {
 43   return __doapl (this, r);
 44 }
 45 
 46 inline complex&
 47 __doami (complex* ths, const complex& r)
 48 {
 49   ths->re -= r.re;
 50   ths->im -= r.im;
 51   return *ths;
 52 }
 53  
 54 inline complex&
 55 complex::operator -= (const complex& r)
 56 {
 57   return __doami (this, r);
 58 }
 59  
 60 inline complex&
 61 __doaml (complex* ths, const complex& r)
 62 {
 63   double f = ths->re * r.re - ths->im * r.im;
 64   ths->im = ths->re * r.im + ths->im * r.re;
 65   ths->re = f;
 66   return *ths;
 67 }
 68 
 69 inline complex&
 70 complex::operator *= (const complex& r)
 71 {
 72   return __doaml (this, r);
 73 }
 74  
 75 inline double
 76 imag (const complex& x)
 77 {
 78   return x.imag ();
 79 }
 80 
 81 inline double
 82 real (const complex& x)
 83 {
 84   return x.real ();
 85 }
 86 
 87 inline complex
 88 operator + (const complex& x, const complex& y)
 89 {
 90   return complex (real (x) + real (y), imag (x) + imag (y));
 91 }
 92 
 93 inline complex
 94 operator + (const complex& x, double y)
 95 {
 96   return complex (real (x) + y, imag (x));
 97 }
 98 
 99 inline complex
100 operator + (double x, const complex& y)
101 {
102   return complex (x + real (y), imag (y));
103 }
104 
105 inline complex
106 operator - (const complex& x, const complex& y)
107 {
108   return complex (real (x) - real (y), imag (x) - imag (y));
109 }
110 
111 inline complex
112 operator - (const complex& x, double y)
113 {
114   return complex (real (x) - y, imag (x));
115 }
116 
117 inline complex
118 operator - (double x, const complex& y)
119 {
120   return complex (x - real (y), - imag (y));
121 }
122 
123 inline complex
124 operator * (const complex& x, const complex& y)
125 {
126   return complex (real (x) * real (y) - imag (x) * imag (y),
127                real (x) * imag (y) + imag (x) * real (y));
128 }
129 
130 inline complex
131 operator * (const complex& x, double y)
132 {
133   return complex (real (x) * y, imag (x) * y);
134 }
135 
136 inline complex
137 operator * (double x, const complex& y)
138 {
139   return complex (x * real (y), x * imag (y));
140 }
141 
142 complex
143 operator / (const complex& x, double y)
144 {
145   return complex (real (x) / y, imag (x) / y);
146 }
147 
148 inline complex
149 operator + (const complex& x)
150 {
151   return x;
152 }
153 
154 inline complex
155 operator - (const complex& x)
156 {
157   return complex (-real (x), -imag (x));
158 }
159 
160 inline bool
161 operator == (const complex& x, const complex& y)
162 {
163   return real (x) == real (y) && imag (x) == imag (y);
164 }
165 
166 inline bool
167 operator == (const complex& x, double y)
168 {
169   return real (x) == y && imag (x) == 0;
170 }
171 
172 inline bool
173 operator == (double x, const complex& y)
174 {
175   return x == real (y) && imag (y) == 0;
176 }
177 
178 inline bool
179 operator != (const complex& x, const complex& y)
180 {
181   return real (x) != real (y) || imag (x) != imag (y);
182 }
183 
184 inline bool
185 operator != (const complex& x, double y)
186 {
187   return real (x) != y || imag (x) != 0;
188 }
189 
190 inline bool
191 operator != (double x, const complex& y)
192 {
193   return x != real (y) || imag (y) != 0;
194 }
195 
196 #include <cmath>
197 
198 inline complex
199 polar (double r, double t)
200 {
201   return complex (r * cos (t), r * sin (t));
202 }
203 
204 inline complex
205 conj (const complex& x) 
206 {
207   return complex (real (x), -imag (x));
208 }
209 
210 inline double
211 norm (const complex& x)
212 {
213   return real (x) * real (x) + imag (x) * imag (x);
214 }
215 
216 #endif   //__MYCOMPLEX__
View Code

complex_test.cpp

 1 #include <iostream>
 2 #include "complex.h"
 3 
 4 using namespace std;
 5 
 6 ostream&
 7 operator << (ostream& os, const complex& x)
 8 {
 9   return os << '(' << real (x) << ',' << imag (x) << ')';
10 }
11 
12 int main()
13 {
14   complex c1(2, 1);
15   complex c2(4, 0);
16 
17   cout << c1 << endl;
18   cout << c2 << endl;
19   
20   cout << c1+c2 << endl;
21   cout << c1-c2 << endl;
22   cout << c1*c2 << endl;
23   cout << c1 / 2 << endl;
24   
25   cout << conj(c1) << endl;
26   cout << norm(c1) << endl;
27   cout << polar(10,4) << endl;
28   
29   cout << (c1 += c2) << endl;
30   
31   cout << (c1 == c2) << endl;
32   cout << (c1 != c2) << endl;
33   cout << +c2 << endl;
34   cout << -c2 << endl;
35   
36   cout << (c2 - 2) << endl;
37   cout << (5 + c2) << endl;
38   
39   return 0;
40 }
View Code

头文件

  • 防卫式声明

类设计

  • 数据放在private

构造函数

  • initialization list 执行速度比{ }中快
  • 以什么方式创建对象,怎么想的就写几种构造函数(overloading)
  • 同名的函数可以有不止一个,两个real(),一个取得实部,一个设置实部(函数在编译器中的实际名称是函数名+参数名+参数个数)
  • complex(double r = 0, double i = 0):re(r),im(i){...}和complex():re(0),im(0){...}  不能同时存在,编译器无法选择
  • complex c1;和complex c2();  含义相同
  • 通常情况,构造函数是public的,只有一个例外,单例模式(外界只能用自己类中创建的一份实例)

const member functions(常量成员函数)

  • 对不改变数据的函数,在函数名后加const。如:double real() const { return re; }
  • 不加的话,使用者用const型数据调用该函数时会出错。如:const complex c1(2,1) ; cout<< c1.real() ;
  • const只能修饰输入参数,成员函数省略了this指针,所以const没地方放,只好放在函数体外了
  • 在普通的非 const成员函数中,this的类型是一个指向类类型对象的 const指针,可以改变this所指向的值,但不能改变 this所保存的地址
  • 在 const成员函数中,this的类型是一个指向 const类类型对象的 const指针。既不能改变 this所指向的对象,也不能改变 this所保存的地址

参数传递 pass by value vs. pass by reference( to const )

  • complex ( double r = 0 ; double i = 0 )  把数据整包传过去,效率较低(此处传一个double和效率和传引用一样,都是4byte)  complex c1(2,1); 
  • complex& operator +=  ( const complex& );   传引用,相当于传指针,尽量采用;若希望传递后变量不更改就加const限制  c2 += c1;
  • ostream& operator << ( ostream& os, const complex& x){...}  第一个参数没有加const,是因为函数体中会改变os的值

返回值传递 return by value vs. return by reference( to const )

  • double real() const { return re; }  传值
  • complex& operator +=  ( const complex& );  传引用,尽量采用

friend(友元)

  • 朋友可以来拿钱(数据)
  • 直接拿数据,打破了封装,也可设计为通过函数拿数据
  • friend complex& __doapl ( complex*, const complex& ) ;
  • inline complex& __doapl( complex* ths, const complex& r ) { ths->re += r.re ; ths->im += r.im; return *ths ; }

相同class的各个objected互为friends

  • int func ( const complex& param ) { return param.re + paream.im ; }
  • c2.func ( c1 ) ;

class body 外的各种定义

什么时候可以pass by reference,什么时候可以return by reference

  • inline complex& __doapl( complex* ths, const complex& r ) { ths->re += r.re ; ths->im += r.im; return *ths ; }
  • 两参数相加后,结果放到第一个参数中,第一个参数被改动,第二个不会被改动
  • 这种情况能用return by reference,因为函数结束后第一个参数不会消失
  • 在函数中创建一个地方放结果,则不能用return by reference,因为函数结束后local变量会消失

操作符重载(成员函数)

  • c2 += c1;
  • inline compex& complex::operator += ( const complex& r){...}
  • 在编译器中的完整形式:inline compex& complex::operator += ( this, const complex& r){...}
  • 编译器在执行时,检查类中定义的运算作用在左值上,c2对应this,c1对应r
  • this为调用者(“谁”调用的),编译器自动把c2的地址传入this
  • 函数嵌套 60-73 便于复用
  • doapl为“do assignment plus”即“做赋值加法”的缩写

return by reference 语法分析

  • 60声明中返回值为引用,而66中定义为指针:返回object,接收object的引用
  • 传递端无需知道接收端的接收方式(在接收端设计)
  • 返回类型写void有隐患,导致使用者不能连续赋值如,c3 += c2 += c1 ;  
  • 其他如 << 和 >> 也有此问题

 操作符重载(非成员函数)

  • + 写成全局函数,因为会有复数加其他类型数据的情况(一共写了3个+函数)
  • c2 = c1 + c2; c2 = c1 + 5; c2 = 7 + c1;
  • 全局函数,无this指针
  • return by value,因为返回local object
  • 临时变量存储+的结果,之前是把右值加到左值,返回左值
  • typename(); 创建临时对象,没有名字,下一行就没了
  • 正号运算符虽然没改变参数值,但也不能返回&,编译器会报错
  • << 必须写成全局,因为标准库只能识别内置数据类型,无法识别object<<cout
  • cout是一个object,type是ostream
  • 参数ostream前不可加const,因为os在函数中会改变
  • 返回值不是void,便于继续接收右边的输出,如:cout<<c1<<conj(c1)
  • 返回值ostream前不可加const,因为连续输出时返回值会改变
  • 返回值本来就有,不是local的,所以传引用

原文地址:https://www.cnblogs.com/cxc1357/p/12273955.html