C++期末复习超详细总结知识点(期末冲刺)

《MySql面试专题》

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

《MySql性能优化的21个最佳实践》

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

《MySQL高级知识笔记》

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

文中展示的资料包括:**《MySql思维导图》《MySql核心笔记》《MySql调优笔记》《MySql面试专题》《MySql性能优化的21个最佳实践》《MySq高级知识笔记》**如下图

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

关注我,点赞本文给更多有需要的人

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

default:执行语句;break;

}

  • switch语句中表达式类型只能是整型或者字符型

  • case里如果没有break,那么程序会一直向下执行

3.2、循环结构


3.2.1、while

作用:满足循环条件,执行循环语句

语法:while(循环条件){ 循环语句 }

**解释:**只要循环条件的结果为真,就执行循环语句

3.2.2、do…while

作用: 满足循环条件,执行循环语句

语法: do{ 循环语句 } while(循环条件);

注意:与while的区别在于do…while会先执行一次循环语句,再判断循环条件(这里常考两者区别,记住无论怎样,do…while都会必然执行一次循环语句)

3.2.3、for

  • for循环中的表达式,要用分号进行分隔

int main() {

for (int i = 0; i < 10; i++)

{

cout << i << endl;

}

system(“pause”);

return 0;

}

3.3、跳转语句


3.3.1、break

作用: 用于跳出选择结构或者循环结构

3.3.2、continue

作用:在循环语句中,跳过本次循环中余下尚未执行的语句,继续执行下一次循环

注意:continue并没有使整个循环终止,而break会跳出循环

4、数组

======================================================================

数组:所谓数组,就是一个集合,存放相同类型的数据元素

  • 数组中的每个数据元素都是相同的数据类型

  • 数组是由连续的内存位置组成的

4.1、一维数组


一维数组定义的三种方式:

  1. 数据类型 数组名[ 数组长度 ];(常用,了解其余两种即可)

  2. 数据类型 数组名[ 数组长度 ] = { 值1,值2 ...};

  3. 数据类型 数组名[ ] = { 值1,值2 ...};

int score[10];

int score2[10] = { 100, 90,80,70,60,50,40,30,20,10 };

int score3[] = { 100,90,80,70,60,50,40,30,20,10 };

  • 数组中下标是从0开始索引

  • 在对全部数组元素赋初值时,可以不指定数组长度

  • 直接打印数组名,可以查看数组所占内存的首地址

  • 对数组名进行sizeof,可以获取整个数组占内存空间的大小

  • 以上三种方式并不要求都会,但是需要都见过,防止在程序改错中乱改

4.1.1、一维数组初始化

  1. 在定义数组时分别对数组元素赋予初值。例如

int a[10]={0,1,2,3,4,5,6,7,8,9};

  1. 可以只给一部分元素赋值。例如

int a[10]={0,1,2,3,4};

  1. 如果想使一个数组中全部元素值为1,可以写成

int a[10]={1,1,1,1,1,1,1,1,1,1};

int a[10]={1*10}; // 错误写法,不能给数组整体赋初值

  1. 在对全部数组元素赋初值时,可以不指定数组长度

int a[5]={1,2,3,4,5};

// 可以写成

int a[]={1,2,3,4,5};

4.2、二维数组


二维数组定义的四种方式:

  1. 数据类型 数组名[ 行数 ][ 列数 ];

  2. 数据类型 数组名[ 行数 ][ 列数 ] = { {数据1,数据2 } ,{数据3,数据4 } };

  3. 数据类型 数组名[ 行数 ][ 列数 ] = { 数据1,数据2,数据3,数据4};

  4. 数据类型 数组名[ ][ 列数 ] = { 数据1,数据2,数据3,数据4};

int arr[2][3];

int arr2[2][3] =

{

{1,2,3},

{4,5,6}

};

int arr3[2][3] = { 1,2,3,4,5,6 };

int arr4[][3] = { 1,2,3,4,5,6 };

  • 以上4种定义方式,利用第二种更加直观,提高代码的可读性

  • 如果对全部元素赋初值,定义数组时对第一维的长度可以不指定,但是第二维的长度不能省略

4.3、字符数组


  • 用来存放字符数据的数组是字符数组,字符数组中的一个元素存放一个字符

定义

char c[10] = {′I′,′ ′,′a′,′m′,′ ′,′h′,′a′,′p′,′p′,′y′};

赋值

只能对字符数组的元素赋值,而不能用赋值语句对整个数组赋值

char c[5];

c={′C′,′h′,′i′,′n′,′a′}; //错误,不能对整个数组一次赋值

C[0]=′C′; c[1]=′h′; c[2]=′i′; c[3]=′n′; c[4]=′a′; //对数组元素赋值,正确

int a[5],b[5]={1,2,3,4,5};

a=b; //错误,不能对整个数组整体赋值

a[0]=b[0]; //正确,引用数组元素

4.4、字符串函数


  • 字符串连接函数 strcat

  • 字符串复制函数 strcpy

  • 字符串比较函数 strcmp

  • 字符串长度函数 strlen

5、函数

======================================================================

作用:将一段经常使用的代码封装起来,减少重复代码

5.1、函数定义


函数的定义一般主要有5个步骤:

1、返回值类型

2、函数名

3、参数表列

4、函数体语句

5、return 表达式

语法:

返回值类型 函数名 (参数列表)

{

函数体语句

return表达式

}

  • 返回值类型 :一个函数可以返回一个值。在函数定义中

  • 函数名:给函数起个名称

  • 参数列表:使用该函数时,传入的数据

  • 函数体语句:花括号内的代码,函数内需要执行的语句

  • return表达式: 和返回值类型挂钩,函数执行完后,返回相应的数据

示例:定义一个加法函数,实现两个数相加

//函数定义

int add(int num1, int num2)

{

int sum = num1 + num2;

return sum;

}

5.2、函数调用


功能:使用定义好的函数

语法:函数名(参数)

int result = add(10,20);

  • 函数定义里小括号内称为形参,函数调用时传入的参数称为实参

  • 例如此处的num1,num2 为形参,10,20为实参

  • 函数不能嵌套定义但是可以嵌套调用(常考)

5.3、函数声明


  • 函数的声明可以多次,但是函数的定义只能有一次

//声明可以多次,定义只能一次

//声明

int max(int a, int b);

int max(int a, int b);

//定义

int max(int a, int b)

{

return a > b ? a : b;

}

int main() {

int a = 100;

int b = 200;

cout << max(a, b) << endl;

system(“pause”);

return 0;

}

5.4、值传递


  • 所谓值传递,即单向传递,就是函数调用时实参将数值传入给形参,而不能由形参传回来给实参。

  • 值传递时,如果形参发生改变,并不会影响实参(值传递时,形参是修饰不了实参的),请务必理解并记住,此处因篇幅就不进行讲解了!

5.5、函数默认参数


在C++中,函数的形参列表中的形参是可以有默认值的。

语法:返回值类型 函数名 (参数= 默认值){}

int func(int a, int b = 10, int c = 10) {

return a + b + c;

}

//1. 如果某个位置参数有默认值,那么从这个位置往后,从左向右,必须都要有默认值

//2. 如果函数声明有默认值,函数实现的时候就不能有默认参数

int func2(int a = 10, int b = 10);

int func2(int a, int b) {

return a + b;

}

int main() {

cout << "ret = " << func(20, 20) << endl;

cout << "ret = " << func(100) << endl;

system(“pause”);

return 0;

}

  • 如果某个位置参数有默认值,那么从这个位置往后,从左向右,必须都要有默认值

  • 如果函数声明有默认值,函数实现的时候就不能有默认参数

5.6、函数占位参数


C++中函数的形参列表里可以有占位参数,用来做占位,调用函数时必须填补该位置

语法: 返回值类型 函数名 (数据类型){}

//函数占位参数 ,占位参数也可以有默认参数

void func(int a, int) {

cout << “this is func” << endl;

}

int main() {

func(10,10); //占位参数必须填补

system(“pause”);

return 0;

}

5.7、函数重载


作用:函数名可以相同,提高复用性

函数重载满足条件:

  • 函数名称相同

  • 函数参数类型不同 或者 个数不同 或者 顺序不同

注意: 函数的返回值不可以作为函数重载的条件

//函数重载需要函数都在同一个作用域下

void func()

{

cout << “func 的调用!” << endl;

}

void func(int a)

{

cout << “func (int a) 的调用!” << endl;

}

void func(double a)

{

cout << “func (double a)的调用!” << endl;

}

void func(int a ,double b)

{

cout << “func (int a ,double b) 的调用!” << endl;

}

void func(double a ,int b)

{

cout << “func (double a ,int b)的调用!” << endl;

}

//函数返回值不可以作为函数重载条件

//int func(double a, int b)

//{

// cout << “func (double a ,int b)的调用!” << endl;

//}

int main() {

func();

func(10);

func(3.14);

func(10,3.14);

func(3.14 , 10);

system(“pause”);

return 0;

}

5.8、重载运算符规则


C++中有以下五个运算符不能重载

| 成员访问运算符 | 成员指针访问运算符 | 域运算符 | 长度运算符 | 条件运算符 |

| — | — | — | — | — |

| . | .* | :: | sizeof | ?: |

重载运算符规则

  1. 重载不能改变运算符运算对象(即操作数)的个数

  2. 重载不能改变运算符的优先级别

  3. 重载不能改变运算符的结合性

  4. 运算符重载函数可以是类的成员函数,也可以是类的友元函数,还可以是既非类的成员函数也不是友元函数的普通函数


什么时候应该用成员函数方式,什么时候应该用友元函数方式?二者有何区别呢?()

  • 一般将单目运算符重载为成员函数,将双目运算符(二元运算符)重载为友元函数

  • 重载为类的成员函数 - operator 函数有一个参数

  • 重载为类的友元函数 - operator 函数有两个参数

  • 只能将重载 “>>” (流插入运算符)和“<<” (流提取运算符)的函数作为友元函数或者普通函数重载,而不能将它们定义为成员函数,因为参数为两个

  • 类型转换运算符只能作为成员函数重载

单目运算符:只有一个操作数,如 !,-(负号),&,*,++,–

双目运算符:*,/,%,+,-,==,!=,<,>,<=,>=,&&,||

5.9、内联函数


  • 指定内置函数的方法很简单,只需在函数首行的左端加一个关键字inline即可。

inline int max(int a,int b);

  • 使用内置函数可以节省运行时间

  • 只有那些规模较小而又被频繁调用的简单函数,才适合于声明为inline函数。

5.10、函数模板


语法:

template

函数声明或定义

解释:

template — 声明创建模板

typename — 表面其后面的符号是一种数据类型,可以用class代替

T — 通用的数据类型,名称可以替换,通常为大写字母

只适用于函数体相同、函数的参数个数相同而类型不同的情况,如果参数的个数不同,则不能用函数模板。

6、指针

======================================================================

指针的作用: 可以通过指针间接访问内存

6.1、指针变量


指针变量定义语法: 数据类型 * 变量名;

  • 请看下方代码示例,理解指针变量的定义与使用,期末一般不会出太难指针的题,但是基本用法一定要会!!

int main() {

//1、指针的定义

int a = 10; //定义整型变量a

//指针定义语法: 数据类型 * 变量名 ;

int * p;

//指针变量赋值

p = &a; //指针指向变量a的地址

cout << &a << endl; //打印数据a的地址

cout << p << endl; //打印指针变量p

//0073F8BC

//0073F8BC

//2、指针的使用

//通过*操作指针变量指向的内存

cout << "*p = " << *p << endl;

// *p = 10

system(“pause”);

return 0;

}

指针变量和普通变量的区别

  • 普通变量存放的是数据,指针变量存放的是地址

  • 指针变量可以通过" * "操作符,操作指针变量指向的内存空间,这个过程称为解引用

总结1: 我们可以通过 & 符号 获取变量的地址

总结2:利用指针可以记录地址

总结3:对指针变量解引用,可以操作指针指向的内存

总结4:所有指针类型在32位操作系统下是4个字节(了解)

6.2、const修饰指针


const修饰指针有三种情况

  1. const修饰指针 — 常量指针

  2. const修饰常量 — 指针常量

  3. const既修饰指针,又修饰常量

int main() {

int a = 10;

int b = 10;

//const修饰的是指针,指针指向可以改,指针指向的值不可以更改

const int * p1 = &a;

p1 = &b; //正确

//*p1 = 100; 报错

//const修饰的是常量,指针指向不可以改,指针指向的值可以更改

int * const p2 = &a;

//p2 = &b; //错误

*p2 = 100; //正确

//const既修饰指针又修饰常量

const int * const p3 = &a;

//p3 = &b; //错误

//*p3 = 100; //错误

system(“pause”);

return 0;

}

技巧:看const右侧紧跟着的是指针还是常量, 是指针就是常量指针,是常量就是指针常量

6.3、指针和数组


作用:利用指针访问数组中元素

  • C++规定,数组名就是数组的起始地址

  • 数组的指针就是数组的起始地址

  • 数组名可以作函数的实参和形参,传递的是数组的地址

int main() {

int arr[] = { 1,2,3,4,5,6,7,8,9,10 };

int * p = arr; //指向数组的指针

cout << "第一个元素: " << arr[0] << endl; //1

cout << "指针访问第一个元素: " << *p << endl; //1

for (int i = 0; i < 10; i++)

{

//利用指针遍历数组

cout << *p << endl;

p++;

}

system(“pause”);

return 0;

}

6.4、指针和函数


作用:利用指针作函数参数,可以修改实参的值(地址传递

//值传递

void swap1(int a ,int b)

{

int temp = a;

a = b;

b = temp;

}

//地址传递

void swap2(int * p1, int *p2)

{

int temp = *p1;

*p1 = *p2;

*p2 = temp;

}

int main() {

int a = 10;

int b = 20;

swap1(a, b); // 值传递不会改变实参

swap2(&a, &b); //地址传递会改变实参

cout << "a = " << a << endl;

cout << "b = " << b << endl;

system(“pause”);

return 0;

}


int a[10];

int *p = &a[0]; // 等价于 int *p = a;

*p = 1; // 等价于 a[0] = 1;

*(p+1) = 2; // 等价于 a[1] = 2;

// 所以 *(p+1) = a[1]; *(p+2) = a[2];

  • C++规定, p+1 指向数组的 下一个元素

void main()

{

int array[10];

// 用数组名作形参,因为接收的是地址,所以可以不指定具体的元素个数

f(array,10);

}

// 形参数组

f(int arr[],int n)

{

}


void main()

{

int a[10];

// 实参数组

f(a,10);

}

// 形参指针

f(int *x,int n)

{

}

总结:如果不想修改实参,就用值传递,如果想修改实参,就用地址传递

6.4、返回指针值的函数


  • 返回指针值的函数简称指针函数。

  • 定义指针函数的一般形式为:

// 类型名 * 函数名(参数列表)

int * a(int x,int y);

7、引用

======================================================================

作用: 给变量起别名

语法: 数据类型 &别名 = 原名

int main() {

int a = 10;

int &b = a;

cout << "a = " << a << endl;

cout << "b = " << b << endl;

// 10

// 10

b = 100;

cout << "a = " << a << endl;

cout << "b = " << b << endl;

// 100

// 100

system(“pause”);

return 0;

}

7.1、引用注意事项


  • 引用必须初始化

int &c; // 错误,引用必须初始化

  • 在声明一个引用后,不能再使之作为另一变量的引用

7.2、引用做函数参数


作用:函数传参时,可以利用引用的技术让形参修饰实参

优点:可以简化指针修改实参

  • 通过引用参数产生的效果同按地址传递是一样的。引用的语法更清楚简单

//1. 值传递

void mySwap01(int a, int b) {

int temp = a;

a = b;

b = temp;

}

//2. 地址传递

void mySwap02(int* a, int* b) {

int temp = *a;

*a = *b;

*b = temp;

}

//参数:把地址传进去,用指针接收

//3. 引用传递

void mySwap03(int& a, int& b) {

int temp = a;

a = b;

b = temp;

}

//参数:别名,下面的a是上面的a的别名,用别名操作修改可原名操作修改是一样的

int main() {

int a = 10;

int b = 20;

// 值传递,形参不会修饰实参

mySwap01(a, b);

cout << “a:” << a << " b:" << b << endl;

// a:10 b:20

// 地址传递,形参会修饰实参

mySwap02(&a, &b);

cout << “a:” << a << " b:" << b << endl;

// a:20 b:10

// 引用传递,形参会修饰实参

mySwap03(a, b);

cout << “a:” << a << " b:" << b << endl;

// a:20 b:10

system(“pause”);

return 0;

}

7.3、引用做函数返回值


作用:引用是可以作为函数的返回值存在的

//数据类型后加&,相当于用引用的方式返回

int& test02() {

// 必须使用静态变量,需加 static 关键字

static int a = 20;

return a;

}

int main(){

int& ref2 = test02();

system(“pause”);

return 0;

}

8、类和对象

========================================================================

8.1、struct和class区别


在C++中 struct和class唯一的区别就在于 默认的访问权限不同

区别:

  • struct 默认权限为公共

  • class 默认权限为私有

8.1、构造函数和析构函数


  • 构造函数:主要作用在于创建对象时为对象的成员属性赋值,构造函数由编译器自动调用,无须手动调用。

  • 析构函数:主要作用在于对象销毁前系统自动调用,执行一些清理工作。


构造函数语法:类名(){}构造和析构很容易出选择题,特点要记住

  1. 构造函数,没有返回值也不写void

  2. 构造函数的名字必须与类名相同

  3. 构造函数可以有参数,因此可以发生重载

  4. 程序在调用对象时候会自动调用构造函数,无须手动调用,而且只会调用一次(构造函数不需用户调用,也不能被用户调用)


析构函数语法: ~类名(){}

  1. 析构函数,没有返回值也不写void

  2. 函数名称与类名相同,在名称前加上符号~

  3. 析构函数不可以有参数,因此不可以发生重载

  4. 程序在对象销毁前会自动调用析构,无须手动调用,而且只会调用一次

class Person

{

public:

//构造函数

Person()

{

cout << “Person的构造函数调用” << endl;

}

//析构函数

~Person()

{

cout << “Person的析构函数调用” << endl;

}

};

void test01()

{

Person p; //在栈上的数据,test01()执行完毕后,释放这个对象

}

int main() {

test01();

system(“pause”);

return 0;

}

8.3、构造函数分类与调用


构造函数按参数分为: 有参构造和无参构造

调用方式:括号法

class Person {

public:

//无参(默认)构造函数

Person() {

cout << “无参构造函数!” << endl;

}

//有参构造函数

Person(int a) {

age = a;

cout << “有参构造函数!” << endl;

}

//析构函数

~Person() {

cout << “析构函数!” << endl;

}

public:

int age;

};

//2、构造函数的调用

//调用无参构造函数

void test01() {

Person p; //调用无参构造函数

}

//调用有参的构造函数

void test02() {

// 括号法,常用

Person p1(10);

}

  • 尽管在一个类中可以包含多个构造函数,但是对于每一个对象来说,建立对象时只执行其中一个构造函数,并非每个构造函数都被执行

8.4、初始化列表


  • C++提供了初始化列表语法,用来初始化属性

语法:构造函数():属性1(值1),属性2(值2)... {}

class Person {

public:

传统方式初始化

//Person(int a, int b, int c) {

// m_A = a;

// m_B = b;

// m_C = c;

//}

//初始化列表方式初始化

Person(int a, int b, int c) :m_A(a), m_B(b), m_C© {}

void PrintPerson() {

cout << “mA:” << m_A << endl;

cout << “mB:” << m_B << endl;

cout << “mC:” << m_C << endl;

}

private:

int m_A;

int m_B;

int m_C;

};

int main() {

Person p(1, 2, 3);

p.PrintPerson();

system(“pause”);

return 0;

}

8.5、类对象作为类成员


C++类中的成员可以是另一个类的对象,我们称该成员为 对象成员

例如:

class A {}

class B

{

A a;

}

  • B类中有对象A作为成员,A为对象成员

  • 那么当创建B对象时,A与B的构造和析构的顺序是谁先谁后?

  • 先调用对象成员的构造,再调用本类构造(如上例中,先调用A的构造函数)

  • 析构顺序与构造相反

8.6、静态成员


静态成员就是在成员变量和成员函数前加上关键字static,称为静态成员

静态成员分为:

  • 静态成员变量

  • 所有对象共享同一份数据

  • 在编译阶段分配内存

  • 类内声明,类外初始化

  • 静态成员函数

  • 所有对象共享同一个函数

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

**示例1 **:静态成员变量

class Person

{

public:

static int m_A; //静态成员变量

//静态成员变量特点:

//1 在编译阶段分配内存

//2 类内声明,类外初始化

//3 所有对象共享同一份数据

private:

static int m_B; //静态成员变量也是有访问权限的

};

int Person::m_A = 10;

int Person::m_B = 10;

void test01()

{

//静态成员变量两种访问方式

//1、通过对象

Person p1;

p1.m_A = 100;

cout << "p1.m_A = " << p1.m_A << endl;

Person p2;

p2.m_A = 200;

cout << "p1.m_A = " << p1.m_A << endl; //共享同一份数据

cout << "p2.m_A = " << p2.m_A << endl;

//2、通过类名

cout << "m_A = " << Person::m_A << endl;

//cout << "m_B = " << Person::m_B << endl; //私有权限访问不到

}

int main() {

test01();

system(“pause”);

return 0;

}

示例2:静态成员函数

class Person

{

public:

//静态成员函数特点:

//1 程序共享一个函数

//2 静态成员函数只能访问静态成员变量

static void func()

{

cout << “func调用” << endl;

m_A = 100;

//m_B = 100; //错误,不可以访问非静态成员变量

}

static int m_A; //静态成员变量

int m_B; //

private:

//静态成员函数也是有访问权限的

static void func2()

{

cout << “func2调用” << endl;

}

};

int Person::m_A = 10;

void test01()

{

//静态成员变量两种访问方式

//1、通过对象

Person p1;

p1.func();

//2、通过类名

Person::func();

//Person::func2(); //私有权限访问不到

}

int main() {

test01();

system(“pause”);

return 0;

}

8.7、const修饰成员函数


常函数:

  • 成员函数后加const后我们称为这个函数为常函数

  • 常函数内不可以修改成员属性

常对象:

  • 声明对象前加const称该对象为常对象

  • 常对象只能调用常函数

8.8、const型数据小结


| 形式 | 含义 |

| — | — |

| Time const t1 | t1 是常对象,其值在任何情况下都不能改变 |

| void Time::fun() const | fun 是 Time类中的常成员函数,可以引用,但不能修改本类中的数据成员 |

| Time * const p | p 是指向Time对象的常指针,P的值不能改变 |

| const Time *p | p是指向 Time 类常对象的指针,其指向的类对象的值不能通过指针来改变 |

| Time &t1 = t; | t1是Time类对象t的引用,二者指向同一段内存空间 |

9、继承

======================================================================

继承的好处:可以减少重复的代码

继承的语法:class 子类 : 继承方式 父类

class A : public B;

A 类称为子类 或 派生类

B 类称为父类 或 基类

9.1、继承方式


继承方式一共有三种:

  • 公共继承

  • 保护继承

  • 私有继承

在这里插入图片描述

简单的说:

  • 公共继承:基类的公用成员和保护成员在派生类中保持原有访问属性,其私有成员仍为基类私有。

  • 私有继承:基类的公用成员和保护成员在派生类中成了私有成员。其私有成员仍为基类私有

  • 保护继承:基类的公用成员和保护成员在派生类中成了保护成员,其私有成员仍为基类私有。

9.2、构造和析构函数


  • 构造函数的主要作用是对数据成员初始化

  • 派生类是不能继承基类的析构函数,也需要通过派生类的析构函数去调用基类的析构函数

  • 继承中 先调用父类构造函数,再调用子类构造函数,析构顺序与构造相反

9.3、不能继承


  • C++中,不能被派生类继承的是:构造函数

9.4、继承特点


单继承:一个派生类只从一个基类派生

多继承:一个派生类有两个或多个基类的称为多重继承

10、多态

=======================================================================

多态性是指具有不同功能的函数可以用同一个函数名,这样就可以用一个函数名调用不同内容的函数

多态分为两类

  • 静态多态: 函数重载 和 运算符重载属于静态多态,复用函数名

  • 动态多态: 派生类和虚函数(virtual function)实现运行时多态

10.1、虚函数


什么是虚函数?

  • 在基类用 virtual 声明成员函数为虚函数

虚函数的作用

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

虚函数的使用方法

  • 在基类用 virtual 声明成员函数为虚函数。这样就可以在派生类中重新定义此函数,为它赋予新的功能,并能方便地被调用

  • 在类外定义虚函数时,不必再加virtual

  • 在派生类中重新定义此函数,要求函数名、函数类型、函数参数个数和类型全部与基类的虚函数相同,并根据派生类的需要重新定义函数体

C++规定,当一个成员函数被声明为虚函数后,其派生类中的同名函数都自动成为虚函数。因此在派生类重新声明该虚函数时,可以加virtual,也可以不加,但习惯上一般在每一层声明该函数时都加virtual,使程序更加清晰

class Animal

{

public:

//Speak函数就是虚函数

//函数前面加上virtual关键字,变成虚函数,那么编译器在编译的时候就不能确定函数调用了。

virtual void speak()

{

cout << “动物在说话” << endl;

}

};

class Cat :public Animal

{

public:

void speak()

{

cout << “小猫在说话” << endl;

}

};

class Dog :public Animal

{

public:

void speak()

{

cout << “小狗在说话” << endl;

}

};

//我们希望传入什么对象,那么就调用什么对象的函数

//如果函数地址在编译阶段就能确定,那么静态联编

//如果函数地址在运行阶段才能确定,就是动态联编

void DoSpeak(Animal & animal)

{

animal.speak();

}

//

//多态满足条件:

//1、有继承关系

//2、子类重写父类中的虚函数

//多态使用:

//父类指针或引用指向子类对象

void test01()

{

Cat cat;

DoSpeak(cat);

Dog dog;

DoSpeak(dog);

}

int main() {

test01();

system(“pause”);

return 0;

}

多态满足条件

  • 有继承关系

  • 子类重写父类中的虚函数

  1. 纯虚函数
  • 纯虚函数是在声明虚函数时被“初始化”为0的函数。声明纯虚函数的一般形式是

virtual 函数类型 函数名 (参数表列) =0;

  • 纯虚函数没有函数体

  • 最后面的 =0 ,并不表示函数返回值为0,它只告诉编译系统“老子是纯虚函数”

  • 纯虚函数只有函数的名字而不具备函数的功能,不能被调用

  1. 抽象类
  • 凡是包含纯虚函数的类都是抽象类

  • 一个基类如果包含一个或一个以上纯虚函数,就是抽象基类。抽象基类不能也不必要定义对象、

11、文件操作

=========================================================================

C++中对文件操作需要包含头文件 < fstream >

文件类型分为两种

  1. 文本文件 - 文件以文本的ASCII码形式存储在计算机中

  2. 二进制文件 - 文件以文本的二进制形式存储在计算机中,用户一般不能直接读懂它们

操作文件的三大类:

  1. ofstream:写操作

  2. ifstream: 读操作

  3. fstream : 读写操作

11.1、文本文件


5.1.1写文件

写文件步骤如下:

  1. 包含头文件

#include

  1. 创建流对象

ofstream ofs;

  1. 打开文件

ofs.open(“文件路径”,打开方式);

  1. 写数据

ofs << “写入的数据”;

  1. 关闭文件

ofs.close();

文件打开方式:

| 打开方式 | 解释 |

| — | — |

| ios::in | 为读文件而打开文件 |

| ios::out | 为写文件而打开文件 |

| ios::ate | 初始位置:文件尾 |

| ios::app | 追加方式写文件 |

| ios::trunc | 如果文件存在先删除,再创建 |

| ios::binary | 二进制方式 |

注意: 文件打开方式可以配合使用,利用|操作符

**例如:**用二进制方式写文件 ios::binary | ios:: out

示例:

#include

void test01()

{

ofstream ofs;

ofs.open(“test.txt”, ios::out);

ofs << “姓名:张三” << endl;

总结

互联网大厂比较喜欢的人才特点:对技术有热情,强硬的技术基础实力;主动,善于团队协作,善于总结思考。无论是哪家公司,都很重视高并发高可用技术,重视基础,所以千万别小看任何知识。面试是一个双向选择的过程,不要抱着畏惧的心态去面试,不利于自己的发挥。同时看中的应该不止薪资,还要看你是不是真的喜欢这家公司,是不是能真的得到锻炼。其实我写了这么多,只是我自己的总结,并不一定适用于所有人,相信经过一些面试,大家都会有这些感触。

**另外本人还整理收藏了2021年多家公司面试知识点以及各种技术点整理 **

下面有部分截图希望能对大家有所帮助。

在这里插入图片描述

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

s Animal

{

public:

//Speak函数就是虚函数

//函数前面加上virtual关键字,变成虚函数,那么编译器在编译的时候就不能确定函数调用了。

virtual void speak()

{

cout << “动物在说话” << endl;

}

};

class Cat :public Animal

{

public:

void speak()

{

cout << “小猫在说话” << endl;

}

};

class Dog :public Animal

{

public:

void speak()

{

cout << “小狗在说话” << endl;

}

};

//我们希望传入什么对象,那么就调用什么对象的函数

//如果函数地址在编译阶段就能确定,那么静态联编

//如果函数地址在运行阶段才能确定,就是动态联编

void DoSpeak(Animal & animal)

{

animal.speak();

}

//

//多态满足条件:

//1、有继承关系

//2、子类重写父类中的虚函数

//多态使用:

//父类指针或引用指向子类对象

void test01()

{

Cat cat;

DoSpeak(cat);

Dog dog;

DoSpeak(dog);

}

int main() {

test01();

system(“pause”);

return 0;

}

多态满足条件

  • 有继承关系

  • 子类重写父类中的虚函数

  1. 纯虚函数
  • 纯虚函数是在声明虚函数时被“初始化”为0的函数。声明纯虚函数的一般形式是

virtual 函数类型 函数名 (参数表列) =0;

  • 纯虚函数没有函数体

  • 最后面的 =0 ,并不表示函数返回值为0,它只告诉编译系统“老子是纯虚函数”

  • 纯虚函数只有函数的名字而不具备函数的功能,不能被调用

  1. 抽象类
  • 凡是包含纯虚函数的类都是抽象类

  • 一个基类如果包含一个或一个以上纯虚函数,就是抽象基类。抽象基类不能也不必要定义对象、

11、文件操作

=========================================================================

C++中对文件操作需要包含头文件 < fstream >

文件类型分为两种

  1. 文本文件 - 文件以文本的ASCII码形式存储在计算机中

  2. 二进制文件 - 文件以文本的二进制形式存储在计算机中,用户一般不能直接读懂它们

操作文件的三大类:

  1. ofstream:写操作

  2. ifstream: 读操作

  3. fstream : 读写操作

11.1、文本文件


5.1.1写文件

写文件步骤如下:

  1. 包含头文件

#include

  1. 创建流对象

ofstream ofs;

  1. 打开文件

ofs.open(“文件路径”,打开方式);

  1. 写数据

ofs << “写入的数据”;

  1. 关闭文件

ofs.close();

文件打开方式:

| 打开方式 | 解释 |

| — | — |

| ios::in | 为读文件而打开文件 |

| ios::out | 为写文件而打开文件 |

| ios::ate | 初始位置:文件尾 |

| ios::app | 追加方式写文件 |

| ios::trunc | 如果文件存在先删除,再创建 |

| ios::binary | 二进制方式 |

注意: 文件打开方式可以配合使用,利用|操作符

**例如:**用二进制方式写文件 ios::binary | ios:: out

示例:

#include

void test01()

{

ofstream ofs;

ofs.open(“test.txt”, ios::out);

ofs << “姓名:张三” << endl;

总结

互联网大厂比较喜欢的人才特点:对技术有热情,强硬的技术基础实力;主动,善于团队协作,善于总结思考。无论是哪家公司,都很重视高并发高可用技术,重视基础,所以千万别小看任何知识。面试是一个双向选择的过程,不要抱着畏惧的心态去面试,不利于自己的发挥。同时看中的应该不止薪资,还要看你是不是真的喜欢这家公司,是不是能真的得到锻炼。其实我写了这么多,只是我自己的总结,并不一定适用于所有人,相信经过一些面试,大家都会有这些感触。

**另外本人还整理收藏了2021年多家公司面试知识点以及各种技术点整理 **

下面有部分截图希望能对大家有所帮助。

[外链图片转存中…(img-Ibl5qk8r-1715817105821)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

### 部署 Stable Diffusion 的准备工作 为了成功部署 Stable Diffusion,在本地环境中需完成几个关键准备事项。确保安装了 Python 和 Git 工具,因为这些对于获取源码和管理依赖项至关重要。 #### 安装必要的软件包和支持库 建议创建一个新的虚拟环境来隔离项目的依赖关系。这可以通过 Anaconda 或者 venv 实现: ```bash conda create -n sd python=3.9 conda activate sd ``` 或者使用 `venv`: ```bash python -m venv sd-env source sd-env/bin/activate # Unix or macOS sd-env\Scripts\activate # Windows ``` ### 下载预训练模型 Stable Diffusion 要求有预先训练好的模型权重文件以便能够正常工作。可以从官方资源或者其他可信赖的地方获得这些权重文件[^2]。 ### 获取并配置项目代码 接着要做的就是把最新的 Stable Diffusion WebUI 版本拉取下来。在命令行工具里执行如下指令可以实现这一点;这里假设目标路径为桌面下的特定位置[^3]: ```bash git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui.git ~/Desktop/stable-diffusion-webui cd ~/Desktop/stable-diffusion-webui ``` ### 设置 GPU 支持 (如果适用) 当打算利用 NVIDIA 显卡加速推理速度时,则需要确认 PyTorch 及 CUDA 是否已经正确设置好。下面这段简单的测试脚本可以帮助验证这一情况[^4]: ```python import torch print(f"Torch version: {torch.__version__}") if torch.cuda.is_available(): print("CUDA is available!") else: print("No CUDA detected.") ``` 一旦上述步骤都顺利完成之后,就可以按照具体文档中的指导进一步操作,比如调整参数、启动服务端口等等。整个过程中遇到任何疑问都可以查阅相关资料或社区支持寻求帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值