C++面向对象高级编程_侯捷(上1) class without pointer members
2 头文件与类的声明
头文件中的防卫式声明(guard)
complex.h
// 如果没有定义过 __COMPLEX__,向下执行定义的操作,如果定义过了,就不会执行后面的语句
// 这样就不会反复 include 的动作
#ifndef __COMPLEX__
#define __COMPLEX__
...
#endif
3 构造函数
初始化列表 / 赋值
要使用初始化列表的形式对成员变量初始化,而不是在函数体内部对成员变量赋值。因为初始化列表的执行效率高,并且是构造函数特有的。
构造函数有很多种,所以需要重载(overloading)
class Complex
{
public:
Complex(double re=0, double im=0): re(r), im(m) {}
// 此时不能写无参构造函数,因为编译不知道该调用哪个构造函数
// Complex() {re=0; im=0}
private:
double re;
double im;
};
构造函数权限控制 public / private
构造函数一般都是 public 权限,因为在类外创建对象需要调用构造函数。
但是也有将构造函数设置为 private 权限,例如在 Singlton(一种设计模式)中,只允许有一个对象,不允许用户在类外自己随意创建对象。
class A
{
public:
static A& getInstance();
setup() { ... }
private:
A();
A(const A& rhs);
...
};
A& A::getInstance()
{
static A a;
return a;
}
4 参数传递与返回值
class 中的函数可以分为:改变数据内容,不改变数据内容。
如果不改变数据,就在函数后面加 const。
const类型的类对象,只能调用const的成员函数。
double real() const {return re;}
参数传递 传值 / 传引用
参数传递:pass by value vs. pass by reference(to const)
尽量不要pass by value,这样把实参整个数据都传给了形参,当实参占用很多内存时,值传递的效率会下降。
尽量使用pass by reference,相当于传指针,所以传数据非常快。
// pass by value
Complex(double r=0, double i=0): rm(r), im(i) {}
// pass by reference
Complex& operator += (const Complex&);
传引用可能导致实参发生改变,这样虽然传递速度变快了,但数据被破坏了,所以使用 const 修饰形参,可以保证实参数据不被改变。
返回值传递 传值 / 传引用
返回值传递:return by value vs. return by reference(to const)
返回值的传递也尽量 by reference
// return by reference
Complex& operator += (const Complex&);
// return by value
double real() const {return re;}
什么情况下才可以 pass/return by reference
之前将到过:
- 数据尽可能的放在 private 里面;
- 参数尽可能使用 reference 来传,根据情况选择 const(是否要改变实参的数据);
- 返回值也尽量以 reference 来传;
- 在类本体(class body)里面的函数,应该加 const 就要加;
- 构造函数尽量使用初始化列表。
- 什么情况下可以 pass by reference
- 什么情况下可以 return by reference
绝对不可以返回 local objects
// do assignment plus
// 第一个参数将会被改变,第二个参数不会被改变
// 第一个参数指向的空间是函数执行前就存在的,函数执行完仍然存在,所以可以返回引用
// 如果将在函数体内创建的空间的数据的引用传出函数体外,就会出错(语法没错),因为函数结束后,这块空间就死亡了。
inline complex& __doapl(complex* ths, const conplex& r)
{
ths->re += r.re;
ths->im += r.im;
return *ths;
}
friend(友元)
C++ 中的友元可以使用类的 private 成员
friend 打破了 C++ 的封装
相同 class 的各个 objects 互为 friends
public:
int func(const Complex& param)
{return param.re + param.im;}
5 操作符重载与临时对象
operator overloading(操作符重载-1,成员函数) this
所有成员函数隐藏带有一个参数(this),谁(哪个对象)调用这个函数,谁就是this。
传递者无需知道接收者是以 reference 形式接收。
即,实参不变形式,形参是pass by value / reference 都不影响,函数形参接收实参。写法都一样
typename() 创建临时对象,它的声明到下一行就结束了。
第5节末尾是对不带指针的类的总结
看到第7节:三大函数