do{} while语句会先进行一次循环体内部,不管while里的条件?
算法特性:可以有0或多个输入, 至少有1个输出

一、函数

0、函数

C语言中函数的隐含存储类别士extern
实参和与其对应的形参各占用独立的存储单元。
程序进行编译时,不为形式参数分配存储空间。是在调用时分配的。
按地址传递时,形参和实参共用同一存储空间。
形参是局部变量、
image.png

返回值

C语言函数没有给出返回类型,默认是int型,
C++如果没有返回类型,必须指明是void类型, 不能不写,必须明确指出
abort()函数用于不正常地终止一个正在执行的程序。
exit()函数用于正常终止程序。
atexit()函数可以把一些函数注册为退出函数(exit function)。
return 0; 一般0代表的是正常结束
return -1; -1代表非正常结束
return ; void 返回是空,void返回值可以什么也不写,可以写return;
return NULL; 如果数据类型是指针类型,那我们一般成功的时候返回相应的地址,失败的时候返回NULL

多态性

有静态、动态两种方式
1. (编译时)静态:函数重载、运算符重载、模板实现
2. (运行时)动态:虚函数实现
重载多态和强制多态是 指特定多态。
参数多态和包含多态是指通用多态。

1、构造函数

没有函数类型,类可以有多个构造函数
构造函数支持函数重载 另外还可以有拷贝构造函数
explicit构造函数是用来防止隐式转换image.png
答案解析:MyClass a[5],会创建5个对象,所以会自动调用5次构造函数,但是MyClass *b[6],这不会自动调用构造函数,因为这是声明一个指向6个元素的数组的指针,指针声明的时候是不分配空间的,所以不会调用构造函数,没有指向一个有效的内存空间。


析构函数


image.png
输出:image.png
基类中的析构函数没有加virtual变成虚析构(基类指针指向子类对象),应此不调用子类的析构函数

拷贝构造函数

使用情况:
(1)用派生类的对象去初始化基类对象时
(2)函数的形参是类的对象,调用函数进行形参和实参结合时
(3)函数的返回值是类的对象,函数执行返回调用时

2、虚函数

(1)不能重载为内联。虚函数是在运行期的时候确定具体调用的函数,内联是在编译期的时候进行代码展开,两者冲突
(2)包含虚函数的类有this指针;可以被继承
纯虚函数:virtual void fun()=0;

3、友元函数

定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数。
友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类,在这种情况下,整个类及其所有成员都是友元。
如果要声明函数为一个类的友元,需要在类定义中该函数原型前使用关键字 friend

4、fork()函数

fork函数将运行着的程序分成2个(几乎)完全一样的进程,每个进程都启动一个从代码的同一位置开始执行的线程。内存是全部复制
image.png
vfork()创建的子进程共享父进程的地址空间,并且子进程先于父进程执行。共享内存
clone()是可以将父进程资源有选择地复制给子进程,而没有复制的数据结构则通过指针的复制让子进程共享,具体要复制哪些资源给子进程,由参数列表中的clone_flags来决定。另外,clone()返回的是子进程的pid。
clone是fork的升级版本,不仅可以创建进程或者线程,还可以指定创建新的命名空间(namespace)、有选择的继承父进程的内存、甚至可以将创建出来的进程变成父进程的兄弟进程等等

1.fork()函数会把它所在语句以后的语句复制到一个子进程里,单独执行。
2.如果printf函数最后没有“\n”,则输出缓冲区不会被立即清空,而fork函数会把输出缓冲区里的内容也都复制到子进程里。
所以,父进程和子进程各输出2个Hello,共4个。
如果第一个printf(“Hello”);写成printf(“Hello\n”);,则只会输出3个Hello,父进程2个,子进程1个。

5、重载函数

(1)可以使用默认参数。要当心二义性

6、内联函数

关键字:inline
类定义中的定义的函数都是内联函数,即使没有使用 inline 说明符。
用法:当函数代码较小并且被频繁调用的时候
如Max(a,b)
编译时将函数体嵌入在每一个调用处
所有成员函数默认为内联函数。(构造函数也
1.内联函数的函数体内不能含有复杂的结构控制语句,如switch和while,否则编译器将该函数视同普通函数那样产生函数调用代码。
2.递归函数不能被用来作为内联函数。
3.内联函数一般适合于只有1-5行语句的小函数,对于一个含有很多语句的大函数,没必要使用内联函数来实现。
4.内联函数的定义必须出现在内联函数第一次被调用之前。
5.对内联函数不能进行异常接口声明,就是不能声明可能抛出的异常。

7、回调函数

通过函数指针调用
该函数写在高层,低层通过一个函数指针保存这个函数,在某个事件的触发下,低层通过该函数指针调用高层那个函数

8、静态(成员?)函数

静态成员函数只能访问静态成员变量和静态成员函数。

9、内存相关

free()

free函数,作用是释放内存,内存释放是标记删除, 只会修改当前空间的所属状态,并不会清除空间内容。

容器

B.vector 的erase函数 删除指定位置的元素时, 返回值是一个迭代器,指向删除元素下一个元素。删除第一个300后,itor指向其后的300,然后执行itor++,指向了500.

二、函数间

1、重载、重写

image.png
方法重载:方法名称相同,参数列表不同(可以是参数的类型,个数,顺序不同)

2、返回值是指针

定义一个返回值为指针的函数,错误情况: 正确:
image.png image.png
↑char re[20]存在栈区,函数结束就消亡 ↑static,在全局区,指针保留
返回指针空?之后用不了

3、重写

class B
{
public:
virtual void Fun(){}
};
class D: public B
{
public:
void Fun(){}
};
D dd; //子类对象
B pb = ⅆ //父类指针引用子类对象,子类对象退化成父类对象,只能访问父类中定义的成员.但是B的Fun()又virtual修饰的话,就会展现多态行为,会根据实际指针指向的对象判断函数的调用
D
pd = ⅆ
pb->Fun(); //如果没有virtual就是B fun(),有,由于多态性,转为D fun()
pd->Fun(); //D fun()

赋值兼容:

  1. 1.子类对象可以赋值给父类对象<br /> 2.子类对象可以初始化父类对象<br /> 3.父类指针可以指向子类对象<br /> 4.父类引用可以引用子类对象<br />另例:<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/12448378/1646187591863-db6a6d7f-579c-4229-bf7b-178f32a8c3e9.png#clientId=ud6979fc6-3e77-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=378&id=u398c19e5&margin=%5Bobject%20Object%5D&name=image.png&originHeight=756&originWidth=763&originalType=binary&ratio=1&rotation=0&showTitle=false&size=61995&status=done&style=none&taskId=u778afced-25e2-4a2d-b5ca-7c381966e47&title=&width=381.5)<br />A的构造->A的foo->B的bar(因为A的bar是虚函数)<br />barfoob_bar

类的sizeof

如果在类中声明了虚函数(不管是1个还是多个),那么在实例化对象时,编译器会自动在对象里安插一个指针指向虚函数表VTable,在32位机器上,一个对象会增加4个字节来存储此指针,它是实现面向对象中多态的关键。因此,LenB和nLenBObject的值为4;
空类:1B,有虚函数的类:4B
要对齐,不用对齐的是union

4、函数模板

类模板的成员函数都是函数模板
没使用过的成员函数(即函数模板)不会被实例化

5、修饰词

mutable修饰跟类状态无关的数据成员。
普通成员函数后面加上 const 修饰,就是常函数。

三、模板

类模板的格式如下:
templateclass类名{ … };

函数模板的格式如下:
Template 返回类型函数名(参数列表){函数体}
其中,class可以用typename关键字代替。

四、一些函数

1、返回n中1的个数
image.png
2、字符串
ord是将字符串首字母转换成ascii值; chr将ascii转换成字母