《后台开发核心技术与应用实践》(一)

时间:2022-10-31 21:46:34

引言

《后台开发核心技术与应用实践(徐晓鑫)》的学习笔记。

0.绪论

后台开发技术能力体系,自省!

《后台开发核心技术与应用实践》(一)

1.C++编程常用技术

1.1. #include<>#include""

后者先搜索当前目录,再搜索标准头文件目录

1.2. strlen与sizeof的区别

(1)strlen()是函数,在运行时才能计算。参数必须是字符型指针(char*),且必须是以’\0’结尾的。当数组名作为参数传入时,实际上数组已经退化为指针了。它的功能是返回字符串的长度。
(2)sizeof()是运算符,而不是一个函数,在编译时就计算好了,用于计算数据空间的字节数。因此,sizeof不能用来返回动态分配的内存空间的大小。sizeof常用于返回类型和静态分配的对象、结构或数组所占的空间,返回值跟对象、结构、数组所存储的内容没有关系。

1.3. 数组指针与指针数组

数组指针int(*p)[n]:指向一维数组的指针,也称行指针,专门用来指向二维数组
指针数组int*p[n]:不能p=a,可以*p=a赋值这里*p表示指针数组第一个元素的值,a的首地址的值

1.4. 使用引用传递函数参数

使用引用传递函数的参数时,在内存中并没有产生实参的副本,而是对实参直接操作。当使用一般变量传递函数的参数时,当函数发生调用,需要给形参分配存储单元,形参变量是实参变量的副本;如果传递的是对象,还将调用拷贝构造函数。因此,当参数传递的数据较大时,用引用比用一般变量传递参数的效率更高,所占空间更少。

使用指针作为函数的参数虽然也能达到与使用引用同样的效果,但是在被调函数中同样要给形参分配存储单元,且需要重复使用“*指针变量名”的形式进行运算,这很容易产生错误且程序的阅读性较差;另一方面,在主调函数的调用点处,必须用变量的地址作为实参,这些都不太方便。

如果既要提高程序的效率,又要使传递给函数的数据不在函数中被改变,就应该使用常引用const 类型&引用名=目标变量;

1.5. union判断系统大端/小端

共用体(联合体)里可以定义多种不同数据类型,这些数据共享一段内存,在不同时间里保存不同的数据类型和长度的变量。
《后台开发核心技术与应用实践》(一)

typedef union   
{
char a;
int c;
}Test;

int check() //1--小端 0---大端
{
Test t;
t.c=1;
if(t.a==1)
return 1;
else
return 0;
}

1.6. 结构体、共用体在内存单元占用字节数的计算

一般64位机器上各个数据类型所占的存储空间如下所述。
(1)char:8bit=1byte。
(2)short:16bit=2byte。
(3)int:32bit=4byte。
(4)long:64bit=8byte。
(5)float:32bit=4byte。
(6)double:64bit=8byte。
(7)long long:64bit=8byte。
其中,long类型在32位机器上只占4Byte,其他类型在32位机器和64位机器都是占同样的大小空间。

union中变量共用内存,应以最长的为准,且在共用体内变量的默认内存对齐方式,必须以最长的double(8Byte)对齐。

结构体中所有成员变量都分配空间,且空间总的大小应为结构的节边界数(即结构中占用最大空间的类型所占用的字节数sizeof(double)=8)的倍数。

1.7. 预处理

宏定义中注意加括号,尤其是带参数的宏定义,要给宏体中的每个参数加上括号,并在整个宏体上再加一个括号。

do…while(0)将一组语句包成一个复合语句,以防预处理时被拆散

__cplusplus是C++的预定义宏,表示当前开发环境是C++。在C++语言中,为了支持重载机制,在编译生成的汇编代码中,会对函数名字进行一些处理(通常称为函数名字改编),如加入函数的参数类型或返回类型等,而在C语言中,只是简单的函数名字而已,并不加入其他信息。所以,在C/C++混合编程的环境下,extern”C”块的作用就是告诉C++编译器这段代码要按C标准编译,以尽可能地保持C++与C的兼容性。

2. 面向对象的C++

2.1. 类和结构体

struct中的成员访问权限默认是public,而class中则默认是private的。
在C语言里,struct中不能定义成员函数,而在C++中,增加了class类型后,扩展了struct的功能,struct中也能定义成员函数了。
一个成员函数如果在类中定义,在定义结束的}之后是不需要加分号的;仅声明的话需要加分号。

2.2. 对象的存储空间

空类占1byte
静态数据成员不占空间
成员函数不占空间
构造函数和析构函数不占空间
如果一个类中有一个或者多个虚函数,没有成员变量,那么类相当于含有一个指向虚函数表的指针,64位机占8Byte。
函数代码是存储在对象空间之外的,而且,函数代码段是公用的。

2.3. 模板类

(1)先写一个实际的类,类名为类模板名。
(2)将此类中准备改变的类型名改用一个自己指定的虚拟类型名。
(3)在类声明前面加入一行,格式为:template <class 自定义虚拟类型名>
(4)用类模板定义对象时用以下形式

类模板名<实际类型名>对象名;
类模板名<实际类型名>对象名(实参表列);

(5)如果在类模板外定义成员函数,应写成类模板形式:

template<class 自定义虚拟类型名>
函数类型 类模板名<自定义虚拟类型名>::成员函数名(函数形参表列) {

}

2.4. 构造函数和析构函数的调用

(1)在全局范围中定义的对象(即在所有函数之外定义的对象),它的构造函数在文件中的所有函数(包括main函数)执行之前调用。但如果一个程序中有多个文件,而不同的文件中都定义了全局对象,则这些对象的构造函数的执行顺序是不确定的。当main函数执行完毕或调用exit函数时(此时程序终止),调用析构函数。
(2)如果定义的是局部自动对象(如在函数中定义对象),则在建立对象时调用其构造函数。如果函数被多次调用,则在每次建立对象时都要调用构造函数。在函数调用结束、对象释放时先调用析构函数。
(3)如果在函数中定义静态(static)局部对象,则只在程序第一次调用此函数建立对象时调用构造函数一次,在调用结束时对象并不释放,因此也不调用析构函数,只在main函数结束或调用exit函数结束程序时,才调用析构函数。

2.5. 派生类的构造函数与析构函数的调用顺序

构造函数的调用顺序规则如下所述
1)基类构造函数。如果有多个基类,则构造函数的调用顺序是某类在类派生表中出现的顺序,而不是它们在成员初始化表中的顺序。
2)成员类对象构造函数。如果有多个成员类对象,则构造函数的调用顺序是对象在类中被声明的顺序,而不是它们出现在成员初始化表中的顺序。
3)派生类构造函数。
而析构函数的调用顺序与构造函数的调用顺序正好相反,将上面3点内容中的顺序反过来用就可以了。

2.6. 多态

虚函数的作用是允许在派生类中重新定义与基类同名的函数,并且可以通过基类指针或引用来访问基类和派生类中的同名函数。

通过虚函数与指向基类对象的指针变量的配合使用,就能方便地调用同一类族中不同类的同名函数,只要先用基类指针指向需要调用函数的对象即可。

纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加“=0”

构造函数不能声明时为虚函数,析构函数可以声明为虚函数,析构函数不是虚函数容易引发内存泄漏。当派生类对象经由一个基类指针被删除、而该派生类带着一个非虚析构函数,会导致对象的派生成分没被销毁掉,这可能形成资源泄漏、损坏数据结构等问题。

2.7 单例模式

单例模式通过类本身来管理其唯一实例,该唯一实例是类的一个普通对象,但设计这个类时,让它只能创建一个实例并提供对此实例的全局访问。

《后台开发核心技术与应用实践》(一)
《后台开发核心技术与应用实践》(二)
《后台开发核心技术与应用实践》(三)
《后台开发核心技术与应用实践》(四)