第一周
C++ 编程简介
我们的目标
- 培养正规的、大气的编程习惯
- 以良好的方式编写C++ Class Object Based(基于对象)
- class without pointer members –
Complex
- class with pointer members –
String
- class without pointer members –
- 学习Classes之间的关系 Object Oriented(面向对象)
- 继承(inheritance)
- 复合(composition)
- 委托(delegation)
C++演化
- C++ 98 (1.0)
- C++ 03 (TR1, Technical Report 1)
- C++ 11 (2.0)
- C++ 14
C++ 语言 C++ 标准库 都很重要
参考书目
C++ Primer
The C++ Programming Language
Effective C++ (经验)
The C++ Standard Library
STL源码剖析
复数类的设计
C与C++关于数据和函数
C语言关键词的限制,数据是全局的。
C++ 把数据和处理数据的函数包在一起,C++的class提供了更多的特性。以class为类型创建出对象objects。
虽然字符串长度不同,但是类中实际是一个指针。
C++ 代码基本形式
include 标准库使用尖括号。
1,系统自带的头文件用尖括号括起来,这样编译器会在系统文件目录下查找。
#include
Header(头文件)中的防卫式声明
避免重复include。
#ifndef __COMPLEX__
#define __COMPLEX__
...
#endif
头文件的布局
class的声明
这里复数类中的实部虚部使用了double
,如果需要其他类型,则需要重复定义,或者使用模板。
class template 模板简介
inline 内联函数
内联函数比较快,但是某些函数无法inline
inline关键字只是对编译器的建议值。
access level 访问级别
private
public
protected
数据部分应该是private
的,允许外界使用的函数声明为public
图中左侧调用方法尝试访问re 和 im,而这些数据是private的。
对数据的访问使用函数封装。
constructor 构造函数
- 构造函数名称与类名相同
- 构造函数可以有参数
- 参数可以有默认值 (default argument)
- 构造函数没有返回类型
赋值使用initialization list 初值列 初始列 初始化列表re(r), im(i)
。
使用initialization list是变量的初始化,在函数体内赋值是变量初始化完成之后再进行赋值,效率比较差。
不带指针的类多半不使用析构函数。
构造函数可以有很多个—— overloading 重载
重载的函数的真实函数名是不同的,取决于编译器。
图中的complex()
函数不能重载,无参数时,无法确定调用哪个构造函数。
构造函数放在private区
构造函数无法被外界调用,但是某些情况下可以这么做,比如单例模式Singleton中。
常量成员函数 const member functions
const
写在()
后面,{}
前面,表示函数中不改变数据内容。
函数的声明const
关键字该加一定要加,比如图中右侧例子,如果函数不加const
,则声明为const
的c1
对象,不能调用c1.real()
方法,因为该函数有可能改变数据内容。影响使用者使用。
参数传递 pass by value vs pass by reference(to const)
尽量不要pass by value,如果数据太大,会占用很多栈空间。
C语言可以传指针,C++有引用,和指针一样的效率,形式漂亮。
尽量传引用。
为了避免引用被修改,可以使用const
。
返回值传递 return by value vs return by reference
返回值尽量传引用。尽量不是一定,可以的情况下,返回引用。
如果要返回在函数中创建的对象,就不要return by reference,局部变量在函数结束后就消失了。
友元 friend
图中声明了一个友元函数,friend 可以提高效率,但是破坏了封装。
相同class各个objects互为友元
如图中,c2
的func
函数可以访问c1
的私有成员。
操作符重载-1 成员函数
+=
是二元操作符,有左数,有右数。所有的成员函数带着一个隐藏的参数this
,这个参数不能自己写出来,所以函数的参数比操作符的目数少1。
return by reference语法分析
传递者无需知道接收者是以reference形式接收,比如__doapl
函数,返回了*ths
,是一个object
,而函数返回值是complex&
,没有问题。+=
的返回值可以实现连续赋值,如c3 += c2 += c1
,根据运算符优先级和结合顺序,返回值就有用了。
操作符重载-2 非成员函数
这里加法运算有3中可能,需要写3个函数,同样的相等,不等也要写3个函数。同一类型的操作符重载,成员函数和非成员函数只能写一个。
为什么不设置为成员函数,因为有实数加复数的情况,成员函数不能做到。
上图的是正号和负号。看参数个数。
这些函数绝对不可以return by reference,因为是在函数里创建的,返回的是local object。正号的返回值可以是return by reference。
☆temp object 临时对象 typename();
如上图返回值return complex(x, y);
,没有名字,生命周期只有一行。
流操作运算符重载
<<
左边是cout
,不可能把该操作符写成成员函数!cout
是ostream
类型,这里不可以加const
,实际上每输出一个东西,都会改变os的数据。
返回值:如果需要连续输出,返回值不能是void,在执行完一次之后,返回的还得是一个cout
,返回reference,没问题。
要点
构造函数的初始化列表的使用。
函数需不需要加const
参数传递尽量考虑 pass by reference, 要不要加const
返回值 return by value,reference
数据尽可能放在private
复习
- 防卫式声明
- class 头
- 复数有实部虚部,数据类型是什么
- 函数有什么
- 构造函数
- 参数
- 是否有默认值
- value reference
- 初始列
- 是否需要其他操作 本例不需要 函数体空
- 参数
- 其他函数
- 可以设计为成员函数或非成员函数
- 函数是否需要const
- 友元函数声明
- inline 内联函数 如果函数体直接在声明时写出,则自动成为inline候选
- 成员函数有this隐藏参数 运算符重载时不写
- 参数是否需要const 引用?
- 返回值是什么 引用? 如果不是local 变量 可以传引用
- 临时对象 类名加小括号
- 操作符重载
- 不同类型 比如不同数的加法
- << 的重载,只能写成非成员函数 返回值
- 需要
include <iostream>
- 构造函数