1. C++面向对象高级开发
1.1 Object Based
- 基本功
- with pointer
- without pointer
- 面对的是单一calss设计
1.2 Object Oriented
- 有关联的calss
- 多个类的设计
1.3 History
C
1972C++
1983new C
->C with Class
->C++
- 大部分版本C++ 98
- C++ 11 (2.0) 新的关键字
- C++ 14
1.4 推荐书
1.4.1 语言类
- 左侧:编译器作者
- 右侧:C++之父
1.4.2 如何书写
1.4.3 标准库
- 牛人 Scott Meyers, Stan Lippman
- C++ Premier 中规中矩
- Effective C++/More Effective C++/Inside C++ Object Model
2. 头文件与类声明
- C语言
- 语言没有关键字,数据必须是全局的
C++语言
- 数据和函数包在一起
- 数据之间不会混杂
- class:就是增强的struct结构,提供了很多关键字
C++,关于数据和函数
- 复数的class设计
- 涉及到实部虚部的设计
- 各种运算关系
- 字符串的struct设计
- 内容通过指针来查找
- 四个字符串,但大小只包含一个指针
- 复数的class设计
2.2 C代码的基本形式
- 不同平台的文件的命名不同.h
, .hpp
, .cpp
- 标准库include <iostream.h>
- 非标准库include "complex.h"
- 数据的输出
- C++使用
cout
方式输出数据来调试 - C的
printf
必须明确数据的类型
- C++使用
2.2.1 Header中的方式声明
- 防卫式声明
- 用头两行来满足,多个文件同时调用时,处理
.h
文件的顺序。
- 用头两行来满足,多个文件同时调用时,处理
- 各类声明
- 复数的类的基本组成
class template介绍
T
根据不同的定义<double>
或<int>
来重新定义
inline 内联函数
- 函数在本体里面定义,就成为inline
- 调用效率高
- 如果函数太复杂,则没法写成inline
访问级别(数据在private是好习惯)
- private不可直接调用,一般是数据部分
- public可以被外界调用
构造函数(不带指针)
- 函数名称与类相同,没有返回类型
- 初始函数列,用
: re(r), im(i)
的写法,这种写法表示初始化,不同于赋值。 - 不带指针,不需要写析构函数
complex c1(2,1)
,调用构造函数,直接复制r=2, i=1
complex c2
,调用构造函数,默认参数complex * p = new complex(4)
,调用构造函数,得到指针。疑问???
构造函数的overloading(重载)
real
取得实部或设定实部,编译时有所不同(如右下角所示)。注意不添加constcomplex () : re(0), im(0) {}
构造函数重构是不行的。
构造函数放在private位置
- 构造函数放在privage后,则不能直接调用
构造函数的设计模式
- 外界的
getInstance
(名称随意)来取得内部函数 - 有这类需求
- 外界的
const member functions(常量成员函数),设计更好的函数
- 函数的后面添加
const
,在real()
和imag()
之后,只是将数据取出来 - 如果没有添加
const
,但使用者调用const complex c1(2,1)
,说明函数不改变数据,则与构造函数冲突。
- 函数的后面添加
参数选择pass by value or pass by reference (to const)(传reference是好习惯)
- by value,将所有的数据的传递过去,避免stack数据过大
- by reference,C语言是通过指针,C++是通过reference(引用的底部就是指针,速度快)
const complex&
传递到const
,传递过去但不修改数值ostream& os
传递到非const
,传递过去,修改数值c2 += c1
传递的是引用ostream& os, const complex& x
,第一步分是非const
,第二部分是const
返回值传递returen by value or by reference (to const)
complex&
返回值传递的是reference
friend友元
- friend可以来拿class里面的数据
complex& __doapl (..)
是frined- 因为是友元,
ths
直接读取re
和im
同一个class的各个object互为友元
int func(..)
目的是计算实部虚部之和,直接读取re
和im
。c2.func(c1)
,用c2的函数来处理复数c1
class body外的各种定义
complex* ths
的数值会被改动const complex& r
的数值不会被改动- 函数的操作结果:创建一个地方存放
- 函数的操作结果:放在其中一个参数
operator overloading 操作符重载之一,成员函数
- 本质上就是一种函数,是C++的特点
- 所有成员函数的隐藏成员
this
,调用者 - 这里
c2
就是this
,编译器会把c2
地址传递过去 c1
就是r
- 实际写的时候,函数成员列表不必写
this
,但可以在里面直接使用 _doapl
,do assignment plus,标准库的代码
- 本质上就是一种函数,是C++的特点
return by reference
return *ths
,返回的是object,但声明指的是complex&
,是引用。二者可以搭配使用*
指返回的value,传递者无需知道接收端用reference形式来接收c1
是value,用complex& r
来接收c3 += c2 += c1
的使用,则重载函数的返回值必须明确complex&
,而不能使用void
class body之外的重定义
- 用引用来传递
const complex& x
- 用引用来传递
非成员函数的操作符重载
+
也许找成员函数,也许找非成员函数,但不能重复- 这里的三个版本对应不同的情况,复数+复数,复数+实数,实数+复数
temp object临时对象
- 蓝色部分,不是return by reference,而是return by value
- 运算的返回值,必定是local
- 在本体运算的结果,如果用reference传出去,如果本体死掉,则数据也就没有了
- 因为这里只是
+
运算,还没有执行=
,所以运算的结果在执行+
运算时,其实不知道要传递给谁 - 而
+=
运算,在执行+=
时,已经知道运算结果是要赋值给左侧的变量,因此可以传reference - 这里使用
typename()
的语法,创建临时对象
- 临时存储临时计算的结果,因为结果既不放在左侧也不放在右侧
- 右侧黄色部分也是临时对象,
complex()
得到(0,0),complex(4,5)
得到(4,5),这两个执行完,内容就消失了。
+
和-
的使用需要明确是加减还是正负- 通过参数的个数来确定
特殊的操作符,必须写成全局函数
cout
是对象,其class name是ostream
,传递引用ostream& os
,但不可以用const
,因为添加之后,os
不可以改变,这与实际不符。因为每次执行<<
,os
都在改变,所以不能添加const
。函数设计:考虑是否用引用,是否用const
- 不能改成
void
,否则则不能使用连续<<
3. Complex的实现过程
- Step 1: 防卫式定义
#ifndef __MYSTRING__
#define __MYSTRING__
...
#endif
- Step 2: 考虑数据类型,在privatre书写
Step 3: 书写哪些函数
- 构造函数是否需要默认值和处置列
- 其他函数是成员函数还是非成员函数
- 每个函数的参数传递是by reference/value
- 取得私有数据的函数
- 函数是否需要添加
const
double real() const { return re;}
double image() const {return im;}
const after a function declaration means that the function is not allowed to change any class members (except ones that are marked mutable). So this use of const only makes sense, and is hence only allowed, for member functions. (http://stackoverflow.com/questions/3141087/what-is-meant-with-const-at-end-of-function-declaration)
Step 4: 本体之外的函数
操作符重载
inline complex&
complex::operator += (const complex& r)
{
return _doapl (this, r)
}
- 考虑函数作用在左侧变量,因此存在隐藏函数
- 右边变量不懂,因此需要
const complex & r
,r
<-> right
- 返回值,仍然需要是复数。如果返回的左侧本来存在,则传引用。
4. 字符串处理:三大函数
- Class with pointer member(s)
- 基本框架
- 基本功能
- 初始化
- 拷贝构造
- 拷贝赋值
- 操作符重载
字符串用指针,因为不确定字符串的长短
- 指针
char*
指向字符 - 重新写四个函数(构造、拷贝构造、字符串重载、析构函数)
- 指针
构造函数
- 字符串的末尾是
- 字符串的末尾是