Geek Band
头文件与类的声明
面向对象的理解:
一个东西将Data(数据)和处理这些数据的函数包在一起,而这些数据只允许给这些函数处理,对于它们之外的函数是不可见。
数据和函数包在一起称为class(类)。class相当于C的struct结构,只是多了更加多的特性在里头,和增加了更多关键字去使用这些特性。
可以这个class作为一种形式,去创建很多很多的objects(对象)。
class的分类:
不带指针的(例如,标准库中处理复数的类)
带指针的(例如,标准库中处理字符串的类)
c++代码基本形式
在主程序中引用
#include <标准库.h>
#include “头文件.h”
(在有的编译器它的后缀名不一定是.h或.cpp)
输入输出标准库声明
对于C++:
#include / #include
using namespace std;
对于C:
#include / #include
头文件的防卫式声明
#ifndef __COMPLEX__//表示如果不曾过定义complex
#define __COMPLEX__//则定义complex
(……)//声明体
#endif//结束
Header(头文件)的布局
#ifndef __COMPLEX__
#define __COMPLEX__
//-------前置声明
include
class ostream;
class complex;
complex&
__doapl (complex* ths,const complex& r);
//-------类-声明
class complex
{
…
};
//-------类-定义
complex::function ()
{
…
}
#endif
3.构造函数
inline(内联)函数
内联函数在百度百科的解释:内联函数是指用inline关键字修饰的函数。在类内定义的函数被默认成内联函数。
函数若在class body内定义完成,便自动成为inline候选人
在类之外定义的,则要加inline前缀,才能成为inline的候选人(建议编译器将它变成inline)
访问级别
public//公共的,可被外界使用的
private//私有的,不可被外界使用
数据是要尽量放在private里面,无一例外;
函数则大多数要放在public内,因为函数主要是被外界调用;
访问级别是一定分开的,而是可以穿插的,即多段“public”和多段“private”分散在class body内;
除此之外还有一个在两者之间的级别,现在暂不涉及。
构造函数
用于表示class被外界构造的表现形式,是类的构造器)
构造函数的名称要跟 类的名称一致
可以拥有参数(如例子中:doubler=0; double i=0 )
可以有默认值(创建时,没有指明参数值就使用默认值)
没有return (返回值)
初始列 :
“re”和“im”是类的参数,专门用于设初值,并且是高速设初值的方法
重载:
使同名的函数可以同时存在,但编译后的实际名称是不同,区别在于参数类型组的不同。
函数重载常常发生在构造函数身上
重载的类型要不一样
当某个类不允许被外界创建对象时,它的远行函数可以放在private:内,这样的类叫做Singleton(单体)的class。
参数传递与返回值
const常量-成员函数
不会改变数据内容的成员函数,切记一定要加上const,是为了防止它的内容发生改变;
否则,在上面这种情况下它可能会出错,造成输出了不是原来想要的值;
因为虽然函数定义是const,而class内部没有做好防护措施。
(我的理解是,机器内部可能会发生错误,而改变了没有加const的内容)
参数传递:pass by value & pass by reference (to const)
pass by value(通过值传递)
pass by reference (通过“引用”传递)—— “引用”在底层就是一个指针;传递速度跟c语言传指针一样的快,所以建议最好所有的函数参数通过“引用”传递;
by reference to const—— 加const后传入的“引用”它的内容将不能被改变;
(只想传值,而不想改变它原来的值时可以使用这种方式传递)
***建议:函数尽量考虑使用“passby reference”
返回值
返回值的类型基本跟c语言的相同;
同样的,返回也可以是“引用”,写法如下:
在类型的后面加上“&”是用来表示reference类型;
friend (友元)
友元:可以让函数自由取得友元函数中的private成员。
友元函数要在类的private中声明,并要在声明前加上“friend”标识;
func()是在这个类里面的一个函数,但在两不同的对象间,如例子中的func()直接获取param中private的参数;
原因:相同class的各个objects互为friends(友元);
class body外的各种定义
两数值运算结果,不被保全的情况下;
例:函数创建的local object(本地变量),函数结束就会立即销毁;
不可以“pass by reference”和“return by reference”;
操作符重载与临时对象
操作符重载1,成员函数
对于成员函数操作符重载的写法
操作符重载:重新定义操作符的功能;
(操作符重载也遵循重载的规则, 相同的重载函数实际上是在参数不同而在编译器中看来是不一样的两个函数, 即,当前调用的会是重载函数组中,参数类型组合与调用的值的类型组合相同的一个)
表示,它是属于“complex”类里头的操作符重载
示例中,“+=”则变成函数,右边是它的调用者,左边即是它的值;
在编译器看来,成员函数的操作符重载函数会有一个this(point)的参数,作者可以调用,但不能在参数表中将它写出来;
this(point)将会指向“调用者”,
所以成员函数操作符重载左边的值不能是value和temp object .
语法分析
传递者无需知道接收者是以什么形式接收;(C的point则不可)
接收者以reference形式接收时,允许by reference和by value方式传递。
为了能实现连串的“赋值”操作符重载函数的返回值不能设计为void;
当返回值不为空时,“c2 += c1”有返回值,且返回值为运算结果时,连串的动作才能实现。
(“+=”被重装定义为复数加法运算的函数, 所以它是一个函数)
class body 之外的各种定义(definitions)
class body 之外的函数定义与调用
三种可能用法:
复数+复数、
复数+ double、
double +复数;
以上为,对于非成员函数操作符重载的写法;
对于成员函数与它的操作各个地方重载写法对比: 前者有“this (point)”,后者为全局(global)函数没有“this”
temp object(临时对象):typename ()
local object会随着函数的结束而销毁 ,不能用return by reference ;
所以上面用了return by value;
typename ()语法 —— 类型名+() ,正如int ();
用于创建temp object (临时对象);
temp object没有名称,它的生命在下一行就结束;
上面黄色部分教都是临时对像,它们的生命也都是在下一行就结束了;
在它们上面的是有名称的,而它们就没有;
其中,的小括号里没有值,它就会设为complex类里的默认值;
class body之外的各种定义(definitions)
正负号的重载
正负号与加减号的分辨:
正负号只有一个参数,而加减号有两个;
以上为“==”和“!=”的重载
“<<”的重装函数和用法
cout是标准库里的一个object,属于ostream class(名为ostream的类)包含于;
为了能实现连串的输出,返回类型必须为ostream&,原因如下:
它连串使用时,是先执行左边的,
(重载并没有改变原来符号的用法, 而是在它的基础上增加了功能或是重定义了功能)
当它的返回值是ostream&类型时,它结束后还是返回“cout”的引用;
执行下一个时,它的返回值(即是“cout”的引用)就会作为下一个的“os”传入;
这样“cout”就可以一直被引用。