[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__
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 }
头文件
- 防卫式声明
类设计
- 数据放在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
- 一步到位Linux中安装配置MySQL及补坑
- 我是如何处理大并发量订单处理的 KafKa部署总结
- 一步到位分布式开发Zookeeper实现集群管理
- 备胎的养成记KeepAlived实现热备负载
- 0基础搭建Hadoop大数据处理-初识
- 入坑系列之HAProxy负载均衡
- 如何开发自己的搜索帝国之Elasticsearch
- NET中解决KafKa多线程发送多主题的问题
- mysql数据与Hadoop之间导入导出之Sqoop实例
- 如何将mysql数据导入Hadoop之Sqoop安装
- 常见的几种Flume日志收集场景实战
- 教你一步搭建Flume分布式日志系统
- 几十条业务线日志系统如何收集处理?
- 0基础搭建Hadoop大数据处理-编程
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法