C++【个人笔记1】

1.C++的初识

1.1 简单入门

#include<iostream>
using namespace std;
int main() {cout << "hello world" << endl;return 0;
}
  1. #include<iostream>; 预编译指令,引入头文件iostream.
  2. using namespace std; 使用标准命名空间
  3. cout << “hello world”<< endl; 和printf功能一样,输出字符串”hello wrold”

问题1:c++头文件为什么没有.h?

在c语言中头文件使用扩展名.h,将其作为一种通过名称标识文件类型的简单方式。但是c++得用法改变了,c++头文件没有扩展名。但是有些c语言的头文件被转换为c++的头文件,这些文件被重新命名,丢掉了扩展名.h(使之成为c++风格头文件),并在文件名称前面加上前缀c(表明来自c语言)。例如c++版本的math.h为cmath.

问题2:using namespace std 是什么?

namespace是指标识符的各种可见范围。命名空间用关键字namespace 来定义。命名空间是C++的一种机制,用来把单个标识符下的大量有逻辑联系的程序实体组合到一起。此标识符作为此组群的名字。

问题3:cout 、endl 是什么?

cout是c++中的标准输出流,endl是输出换行并刷新缓冲区。

1.2 namespace 【命名空间】

C++中自定义命名空间(namespace)及其使用的三种方法_自定义namespace-CSDN博客

由于namespace的概念,使用C++标准程序库的任何标识符时,可 以有三种选择:

1)直接指定标识符。例如std::ostream而不是ostream。完整语句如 下:

std::cout	<<	std::hex	<<	3.4	<<	std::endl;	

2)使用using关键字。

using	std::cout;	
using	std::endl;	
using	std::cin;

3)最方便的就是使用using namespace std;

4.命名空间使用语法

  1. 创建一个命名空间:
namespace A{int a = 10;
}
namespace B{int a = 20;
}
void test(){cout << "A::a : " << A::a << endl;cout << "B::a : " << B::a << endl;
}

        2.命名空间只能全局范围内定义(以下错误写法)

void test(){namespace A{int a = 10;}namespace B{int a = 20;}cout << "A::a : " << A::a << endl;cout << "B::a : " << B::a << endl;
}

        3.命名空间可以嵌套命名

namespace A{int a = 10;namespace B{int a = 20;}
}
void test(){cout << "A::a : " << A::a << endl;cout << "A::B::a : " << A::B::a << endl;
}

        4.命名空间是开放的,可以随时加入新的成员

namespace A{int a = 10;
}namespace A{void func(){cout << "hello namespace!" << endl;}
}

        5.声明和实现可以分离

#pragma oncenamespace MySpace{void func1();void func2(int param);
}void MySpace::func1(){cout << "MySpace::func1" << endl;
}
void MySpace::func2(int param){cout << "MySpace::func2 : " << param << endl;
}

        6.命名空间起别名

namespace veryLongName{int a = 10;void func(){ cout << "hello namespace" << endl; }
}void test(){namespace shortName = veryLongName;cout << "veryLongName::a : " << shortName::a << endl;veryLongName::func();shortName::func();
}

2.C++对C的扩展

2.1 ::作用域运算符

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>using namespace std;//定义一个命名空间
namespace spaccA {int g_a = 10;
}namespace spaceB {int a = 20;namespace spaceC {struct teacher{int id;char name[64];};}namespace spaceD {struct teacher{int id;char name[64];};}using namespace spaceC;}int main(void)
{//using spaccA::g_a;using namespace spaccA;int a = 10;cout << g_a << endl;//spaceB::spaceC::teacher t1;//using spaceB::spaceC::teacher;//teacher t1;//using namespace spaceB::spaceC;//spaceB::spaceC::teacher t1;using namespace spaceB;teacher t1;t1.id = 10;//spaceB::spaceD::teacher t2;//t2.id = 20;return 0;
}

2.2 "实用性“增强

c语言一定要在使用之前先定义

c++可以在使用的时候进行定义

//C语⾔中的变量都必须在作⽤域开始的位置定义!!
//C++中更强调语⾔的“实⽤性”,所有的变量都可以在需要使⽤时再定义。
#include<iostream>
using namespace std;
int main() {int i = 0;cout << "i=" << i << endl;int k = 4;cout << "k=" << k << endl;return 0;
}

2.3 变量检测增强

c语言允许定义多个同名的变量

c++不能定义多个同名变量,即使作用域不同

/*在C语⾔中,重复定义多个同名的全局变量是合法的在C++中,不允许定义多个同名的全局变量C语⾔中多个同名的全局变量最终会被链接到全局数据区的同⼀个地址空间上int	g_var;int	g_var	=	1;C++直接拒绝这种⼆义性的做法。
*/
#include<iostream>
int	g_var;
int	g_var = 1;
int	main(int argc, char* argv[])
{printf("g_var	=	%d\n", g_var);return 0;
}

2.4 C++中所有变量和函数都必须有类型

C++中所有的变量和函数都必须有类型

C语⾔中的默认类型在C++中是不合法的

函数f的返回值是什么类型,参数⼜是什么类型?

函数g可以接受多少个参数?

//i没有写类型,可以是任意类型
int fun1(i){printf("%d\n", i);return 0;
}
//i没有写类型,可以是任意类型
int fun2(i){printf("%s\n", i);return 0;
}
//没有写参数,代表可以传任何类型的实参
int fun3(){ printf("fun33333333333333333\n");return 0;
}//C语言,如果函数没有参数,建议写void,代表没有参数
int fun4(void){printf("fun4444444444444\n");return 0;
}g(){return 10;
}int main(){fun1(10);fun2("abc");fun3(1, 2, "abc");printf("g = %d\n", g());return 0;
}
  1. 在C语言中,int fun() 表示返回值为int,接受任意参数的函数,int fun(void) 表示返回值为int的无参函数。
  2. 在C++ 中,int fun() 和int fun(void) 具有相同的意义,都表示返回值为int的无参函数。

2.5 更严格的类型转换

在C++,不同类型的变量一般是不能直接赋值的,需要相应的强转。

以上c代码c编译器编译可通过,c++编译器无法编译通过。

typedef enum COLOR{ GREEN, RED, YELLOW } color;
int main(){color mycolor = GREEN;mycolor = 10;printf("mycolor:%d\n", mycolor);char* p = malloc(10);return EXIT_SUCCESS;
}

2.6 struct类型加强

  1. c中定义结构体变量需要加上struct关键字,c++不需要。
  2. c中的结构体只能定义成员变量,不能定义成员函数。c++即可以定义成员变量,也可以定义成员函数。
//1. 结构体中即可以定义成员变量,也可以定义成员函数
struct Student{string mName;int mAge;void setName(string name){ mName = name; }void setAge(int age){ mAge = age; }void showStudent(){cout << "Name:" << mName << " Age:" << mAge << endl;}
};//2. c++中定义结构体变量不需要加struct关键字
void test01(){Student student;student.setName("John");student.setAge(20);student.showStudent();
}

2.7 对函数返回参数个数的要求

C传递参数大于实际定义的参数,只会报警告,C++传递参数大于实际定义的参数会报错

2.8 新增的bool类的关键字

bool b=100;//无论将修改为多少,sizeof(b)永远为1

#include	<iostream>
using namespace	std;
int	main(int	argc, char* argv[])
{int	a;bool	b = true;printf("b	=	%d,	sizeof(b)	=	%d\n", b, sizeof(b));//1   1b = 4;a = b;printf("a	=	%d,	b	=	%d\n", a, b);//1   1b = -4;a = b;printf("a	=	%d,	b	=	%d\n", a, b);//1     1a = 10;b = a;printf("a	=	%d,	b	=	%d\n", a, b);//10   1b = 0;printf("b	=	%d\n", b);//0return 0;
}

2.9 三目运算符功能增强

  1. c语言三目运算表达式返回值为数据值,为右值,不能赋值。
	int a = 10;int b = 20;printf("ret:%d\n", a > b ? a : b);//思考一个问题,(a > b ? a : b) 三目运算表达式返回的是什么?//(a > b ? a : b) = 100;//错误//返回的是右值
  1. c++语言三目运算表达式返回值为变量本身(引用),为左值,可以赋值。
int a = 10;int b = 20;printf("ret:%d\n", a > b ? a : b);//思考一个问题,(a > b ? a : b) 三目运算表达式返回的是什么?cout << "b:" << b << endl;//20//返回的是左值,变量的引用(a > b ? a : b) = 100;//返回的是左值,变量的引用cout << "b:" << b << endl;//100

2.10 const增强

const单词字面意思为常数,不变的。它是c/c++中的一个关键字,是一个限定符,它用来限定一个变量不允许改变,它将一个对象转换成一个常量。

1.c语言中的const

们c中的const理解为”一个不能改变的普通变量”,也就是认为const应该是一个只读变量,既然是变量那么就会给const分配内存,并且在c中const是一个全局只读变量,c语言中const修饰的只读变量是外部连接的。

2.c++中的const

在c++中,一个const不必创建内存空间,而在c中,一个const总是需要一块内存空间。在c++中,是否为const常量分配内存空间依赖于如何使用。一般说来,如果一个const仅仅用来把一个名字用一个值代替(就像使用#define一样),那么该存储局空间就不必创建。

3.C/C++中const异同总结

//const	定义常量--->	const	意味只读
const int	a;	
int const	b;	
//第⼀个第⼆个意思⼀样 代表⼀个常整形数
const int	*c;	
//第三个	c是⼀个指向常整形数的指针(所指向的内存数据不能被修改,但是本⾝可以修改)
int	*	const	d;	
//第四个	d	常指针(指针变量不能被修改,但是它所指向内存空间可以被修改)
const int	*	const	e	;	
//第五个	e⼀个指向常整形的常指针(指针和它所指向的内存空间,均不能被修改)

4.const 和 #define 的相同

#include	<iostream>		
//#define	N	10	
int	main()	
{	const int	a	=	1;			const int	b	=	2;			int	array[a	+	b]	=	{0};	int	i	=	0;							for(i	=	0;	i	<	(a+b);	i++)	{																												printf("array[%d]	=	%d\n",	i,	array[i]);	}																																												return 0;																				
}

C++中的const修饰的,是一个真正的常量,而不是C中变量(只读)。在 const修饰的常量编译期间,就已经确定下来了

5.const 和 #define 的区别

#include	<iostream>
void	fun1()	
{	#define	a	10const int	b	=	20;	
}	
void	fun2()	
{	printf("a	=	%d\n",	a);	//printf("b	=	%d\n",	b);
}	
int	main()	
{	fun1();	fun2();	return 0;	
}

  1. const有类型,可进行编译器类型安全检查。#define无类型,不可进行类型检查.
  2. const有作用域,而#define不重视作用域,默认定义处到文件结尾.如果定义在指定作用域下有效的常量,那么#define就不能用。

辨析;
 

#include	<stdio.h>
int	main()
{const int	a = 10;//将a的地址传递给pint* p = (int*)&a;printf("a===>%d\n", a);//10*p = 11;printf("a===>%d\n", a);//10return 0;
}
#include	<iostream>		
//#define	N	10	
int	main()
{const int	a = 1;const int	b = 2;int	array[a + b] = { 0 };int	i = 0;for (i = 0; i < (a + b); i++){printf("array[%d]	=	%d\n", i, array[i]);//0 0 0}return 0;
}
#include	<iostream>
void	fun1()
{
#define	a	10const int	b = 20;
}
void	fun2()
{printf("a	=	%d\n", a);//10//printf("b	=	%d\n",	b);
}
int	main()
{fun1();fun2();return 0;
}

2.11 真正的枚举

c 语言中枚举本质就是整型,枚举变量可以用任意整型赋值。而 c++中枚举 变量, 只能用被枚举出来的元素初始化。

#include<iostream>
using namespace	std;	
enum season	{SPR,SUM,AUT,WIN};	
int	main()	
{	enum	season	s	=	SPR;	//s	=	0;	//	error,	但是C语⾔可以通过s	=	SUM;	cout	<<	"s	=	"	<<	s	<<endl;//1return 0;	
}

3 引⽤(reference)

3.1 引用基本用法

引用是c++对c的重要扩充。在c/c++中指针的作用基本都是一样的,但是c++增加了另外一种给函数传递地址的途径,这就是按引用传递(pass-by-reference),它也存在于其他一些编程语言中,并不是c++的发明。

  1. 变量名实质上是一段连续内存空间的别名,是一个标号(门牌号)
  2. 程序中通过变量来申请并命名内存空间
  3. 通过变量的名字可以使用存储空间

对一段连续的内存空间只能取一个别名吗?

c++中新增了引用的概念,引用可以作为一个已定义变量的别名。

基本语法

Type & ref=val;
int & ref=&a;//表示ref是a的别名
#include<iostream>
using namespace std;
int main() {int a = 10;int& b = a;//int* ba = 11;{int* p = &a;*p = 12;cout << a << endl;//12}b = 14;cout << a <<"" << b << endl;//14 14
}

注意事项:

  1. &在此不是求地址运算,而是起标识作用。
  2. 类型标识符是指目标变量的类型
  1. 必须在声明引用变量时进行初始化。
  2. 引用初始化之后不能改变。
  3. 不能有NULL引用。必须确保引用是和一块合法的存储单元关联。
  4. 可以建立对数组的引用。
//1. 认识引用
void test01(){int a = 10;//给变量a取一个别名bint& b = a;cout << "a:" << a << endl;cout << "b:" << b << endl;cout << "------------" << endl;//操作b就相当于操作a本身b = 100;cout << "a:" << a << endl;cout << "b:" << b << endl;cout << "------------" << endl;//一个变量可以有n个别名int& c = a;//给c取了一个名为”c”的别名c = 200;cout << "a:" << a << endl;cout << "b:" << b << endl;cout << "c:" << c << endl;cout << "------------" << endl;//a,b,c的地址都是相同的cout << "a:" << &a << endl;cout << "b:" << &b << endl;cout << "c:" << &c << endl;
}
//2. 使用引用注意事项
void test02(){//1) 引用必须初始化//int& ref; //报错:必须初始化引用//2) 引用一旦初始化,不能改变引用int a = 10;int b = 20;int& ref = a;ref = b; //不能改变引用//3) 不能对数组建立引用int arr[10];//int& ref3[10] = arr;
}

3.2 注意点 

1.一个变量可以有n个别名

2.操作别名等于操作原数

3.别名和操作数的地址是一样的

4.引用必须初始化

5.一旦初始化,不能进行修改

6.不能对数组建立引用

3.3 建立对数组的引用

方法一:

	typedef int ArrRef[10];int arr[10];ArrRef& aRef = arr;for (int i = 0; i < 10;i ++){aRef[i] = i+1;}for (int i = 0; i < 10;i++){cout << arr[i] << " ";}cout << endl;

方法二:

	int(&f)[10] = arr;for (int i = 0; i < 10; i++){f[i] = i+10;}for (int i = 0; i < 10; i++){cout << arr[i] << " ";}cout << endl;

3.4 函数中的引用

当引用被用作函数参数的时,在函数内对任何引用的修改,将对还函数外的参数产生改变

//值传递
void ValueSwap(int m,int n){int temp = m;m = n;n = temp;
}
//地址传递
void PointerSwap(int* m,int* n){int temp = *m;*m = *n;*n = temp;
}
//引用传递
void ReferenceSwap(int& m,int& n){int temp = m;m = n;n = temp;
}
void test(){int a = 10;int b = 20;//值传递ValueSwap(a, b);cout << "a:" << a << " b:" << b << endl;//地址传递PointerSwap(&a, &b);cout << "a:" << a << " b:" << b << endl;//引用传递ReferenceSwap(a, b);cout << "a:" << a << " b:" << b << endl;
}

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

  1. 函数调用时传递的实参不必加“&”符
  2. 在被调函数中不必在参数前加“*”符

引用作为其它变量的别名而存在,因此在一些场合可以代替指针。C++主张用引用传递取代地址传递的方式,因为引用语法容易且不易出错。

#include	<iostream>
using namespace	std;
int	getA1()
{int	a;a = 10;return	a;
}
int& getA2()
{int	a;a = 10;return	a;
}
int	main(void)
{int	a1 = 0;int	a2 = 0;//值拷⻉a1 = getA1();//将⼀个引⽤赋给⼀个变量,会有拷⻉动作//理解: 编译器类似做了如下隐藏操作,a2	=	*(getA2())a2 = getA2();//将⼀个引⽤赋给另⼀个引⽤作为初始值,由于是栈的引⽤,内存⾮法int& a3 = getA2();cout << "a1	=	" << a1 << endl;cout << "a2	=	" << a2 << endl;cout << "a3	=	" << a3 << endl;return 0;
}
#include	<iostream>
using namespace	std;
//函数当左值
//返回变量的值
int	func1()
{static int	a1 = 10;return	a1;
}
//返回变量本⾝	,	
int& func2()
{static int	a2 = 10;return	a2;
}
int	main(void)
{//函数当右值int	c1 = func1();cout << "c1	=	" << c1 << endl;int	c2 = func2();	//函数返回值是⼀个引⽤,并且当右值cout << "c2	=	" << c2 << endl;//函数当左值//func1()	=	100;				//errorfunc2() = 100;						//函数返回值是⼀个引⽤,并且当左值c2 = func2();cout << "c2	=	" << c2 << endl;return 0;
}

注意点:

  1. 不能返回局部变量的引用。
  2. 函数当左值,必须返回引用。【因为引用定义的函数,返回的是别名】

3.5 引用的本质:指针常量.(int* const ref)

引用的本质在c++内部实现是一个指针常量.

Type& ref = val; // Type* const ref = &val;

c++编译器在编译过程中使用常指针作为引用的内部实现,因此引用所占用的空间大小与指针相同,只是这个过程是编译器内部实现,用户不可见。

//发现是引用,转换为 int* const ref = &a;
void testFunc(int& ref){ref = 100; // ref是引用,转换为*ref = 100
}
int main(){int a = 10;int& aRef = a; //自动转换为 int* const aRef = &a;这也能说明引用为什么必须初始化aRef = 20; //内部发现aRef是引用,自动帮我们转换为: *aRef = 20;cout << "a:" << a << endl;cout << "aRef:" << aRef << endl;testFunc(a);return EXIT_SUCCESS;
}

3.6 指针引用

对于c++中的定义那个,语法清晰多了。函数参数变成指针的引用,用不着取得指针的地址。

struct Teacher{int mAge;
};
//指针间接修改teacher的年龄
void AllocateAndInitByPointer(Teacher** teacher){*teacher = (Teacher*)malloc(sizeof(Teacher));(*teacher)->mAge = 200;  
}
//引用修改teacher年龄
void AllocateAndInitByReference(Teacher*& teacher){teacher->mAge = 300;
}
void test(){//创建TeacherTeacher* teacher = NULL;//指针间接赋值AllocateAndInitByPointer(&teacher);cout << "AllocateAndInitByPointer:" << teacher->mAge << endl;//引用赋值,将teacher本身传到ChangeAgeByReference函数中AllocateAndInitByReference(teacher);cout << "AllocateAndInitByReference:" << teacher->mAge << endl;free(teacher);
}
#include	<iostream>
using namespace	std;
struct	Teacher
{char	name[64];int	age;
};
//在被调⽤函数 获取资源
int	getTeacher(Teacher * *p)
{Teacher* tmp = NULL;if (p == NULL){return	-1;}tmp = (Teacher*)malloc(sizeof(Teacher));if (tmp == NULL){return	-2;}tmp->age = 33;//	p是实参的地址		*实参的地址 去间接的修改实参的值*p = tmp;return 0;
}
//指针的引⽤ 做函数参数
int	getTeacher2(Teacher*& myp)
{//给myp赋值 相当于给main函数中的pT1赋值myp = (Teacher*)malloc(sizeof(Teacher));if (myp == NULL){return	-1;}myp->age = 36;return 0;
}
void	FreeTeacher(Teacher* pT1)
{if (pT1 == NULL){return;}free(pT1);
}
int	main(void)
{Teacher* pT1 = NULL;//1	c语⾔中的⼆级指针getTeacher(&pT1);cout << "age:" << pT1->age << endl;FreeTeacher(pT1);//2	c++中的引⽤ (指针的引⽤)//引⽤的本质 间接赋值后2个条件 让c++编译器帮我们程序员做了。getTeacher2(pT1);cout << "age:" << pT1->age << endl;FreeTeacher(pT1);return 0;
}

3.7 常量引用(const)

常量引用的定义格式:

const Type& ref = val;

注意:

  1. 如果想对一个常量进行引用, 必须是一个const引用。
  2. const修饰的引用,不能修改。

void test01(){int a = 100;const int& aRef = a; //此时aRef就是a//aRef = 200; 不能通过aRef的值a = 120; //OKcout << "a:" << a << endl;//120cout << "aRef:" << aRef << endl;//120
}
void test02(){//不能把一个字面量赋给引用//int& ref = 100;//但是可以把一个字面量赋给常引用//因为const int的级别比int高const int& ref = 100; //int temp = 200; const int& ret = temp;
}

    [const引用使用场景]

    常量引用主要用在函数的形参,尤其是类的拷贝/复制构造函数。

将函数的形参定义为常量引用的好处:

  • 引用不产生新的变量,减少形参与实参传递时的开销。
  • 由于引用可能导致实参随形参改变而改变,将其定义为常量引用可以消除这种副作用。

    如果希望实参随着形参的改变而改变,那么使用一般的引用,如果不希望实参随着形参改变,那么使用常引用。

//const int& param防止函数中意外修改数据
void ShowVal(const int& param){cout << "param:" << param << endl;
}

3.8 例子

C++引用10分钟入门教程

#include	<iostream>
using namespace	std;
int	main(void)
{int	a = 10;	//c编译器分配4个字节内存,	a内存空间的别名int& b = a;		//b就是a的别名-->const * int b=aa = 11;	//直接赋值{int* p = &a;*p = 12;cout << a << endl;//12}b = 14;cout << "a	=	" << a << ",	b	=	" << b << endl;//14 14return 0;
}

结论:可以通过普通参数修改引用,但是不能通过引用修改参数 

#include	<iostream>
using namespace	std;
int main() {int a = 20;int&  ref = a;ref = 30;cout << ref << a << endl;//30  30int b = 40;const int& ref2 = b;b = 100;cout << ref2 << b << endl;//100 100int& rref = ref;rref = 200;cout << rref << ref << a << endl;//200 200 200
}

作业:

1.简述C++中命名空间的作用。

namespace AAA{
    int a;

using AAA::a;
AAA::a;
using namespace AAA;

2. 定义两个命名空间A 和 B 分别在A中和B中定义变量value

#include<iostream>using namespace std;namespace A {int a = 10;
}
namespace B {int b = 20;
}
int main() {using namespace A;using namespace B;cout << A::a << endl;cout << B::b << endl;}

3. C语言的三目运算符 ? : , 可以当左值么? C++的是否可以? 为什么?

c语言的三目运算符不可以当左值,因为返回的是一个常量。

c++的三目运算符可以做左值

4. 下面哪条语句是错误的?为什么?

(1 < 2? a: b) = 100;//正确,因为结果是一个变量,可以被赋值
   
(1 < 2? 10: 20) = 100//错误,因为结果是一个常量,常量不能被常量赋值

5. const int a; 在C++编译器中是否需要初始化,为什么?
 

在c++中,一旦声明一个const变量,则在声明的过程中一定要对起进行初始化

6.temp

int main() {int a = 10;int* p = (int*)&a;//*p:实际上修改的是temp的值*p = 20;cout << a << endl;//20cout << *p << endl;//20}

6. 简述引用的特点?

1.引用本身不占用内存空间,与被引用对象共用内存

2.引用定义时,必须初始化

3.引用的类型必须与被引用对象的类型保持一致 比如:int a; 引用必须使用int&

4.引用只能引用一个对象,一个对象可以被多次引用。

7.判断

int main() {int a = 20;const int& re_a = a;re_a = 30;//错误,不能直接修改const变量}

 4.inline内联函数

https://www.cnblogs.com/chengxuyuancc/archive/2013/04/04/2999844.html

4.1 内联函数的引出

c++从c中继承的一个重要特征就是效率。假如c++的效率明显低于c的效率,那么就会有很大的一批程序员不去使用c++了。

4.2  预处理宏的缺陷

宏函数是预处理器进行的

内联的编译器处理的

预处理器宏存在问题的关键是我们可能认为预处理器的行为和编译器的行为是一样的。当然也是由于宏函数调用和函数调用在外表看起来是一样的,因为也容易被混淆。但是其中也会有一些微妙的问题出现:

问题一:

#define ADD(x,y) x+y
inline int Add(int x,int y){return x + y;
}
void test(){int ret1 = ADD(10, 20) * 10; //希望的结果是300int ret2 = Add(10, 20) * 10; //希望结果也是300cout << "ret1:" << ret1 << endl; //210cout << "ret2:" << ret2 << endl; //300
}

问题二:

#define COMPARE(x,y) ((x) < (y) ? (x) : (y))
int Compare(int x,int y){return x < y ? x : y;
}
void test02(){int a = 1;int b = 3;//cout << "COMPARE(++a, b):" << COMPARE(++a, b) << endl; // 3cout << "Compare(int x,int y):" << Compare(++a, b) << endl; //2
}

4.3 内联函数基本概念:空间换时间

在c++中,预定义宏的概念是用内联函数来实现的,而内联函数本身也是一个真正的函数。内联函数具有普通函数的所有行为。唯一不同之处在于内联函数会在适当的地方像预定义宏一样展开,所以不需要函数调用的开销。因此应该不使用宏,使用内联函数。

注意必须函数体和声明结合在一起,否则编译器将它作为普通函数来对待。

inline void func(int a);
inline int func(int a) {return a;
}

内联函数的确占用空间,但是内联函数相对于普通函数的优势只是省去了函数调用时候的压栈,跳转,返回的开销。我们可以理解为内联函数是以空间换时间

4.4 类内部的内联函数

为了定义内联函数,通常必须在函数定义前面放一个inline关键字。但是在类内部定义内联函数时并不是必须的。任何在类内部定义的函数自动成为内联函数。

class Person{
public:Person(){ cout << "构造函数!" << endl; }void PrintPerson(){ cout << "输出Person!" << endl; }
}

4.5 内联函数和编译器

4.6 注意点

  • 不能存在任何形式的循环语句
  • 不能存在过多的条件判断语句
  • 函数体不能过于庞大
  • 不能对函数进行取址操作

内联仅仅只是给编译器一个建议,编译器不一定会接受这种建议,如果你没有将函数声明为内联函数,那么编译器也可能将此函数做内联编译。一个好的编译器将会内联小的、简单的函数。

4.7 内联函数 VS 宏函数

4.8 总结

5. 函数的默认参数和占位函数

5.1 默认参数

c++在声明函数原型的时可为一个或者多个参数指定默认(缺省)的参数值,当函数调用的时候如果没有指定这个值,编译器会自动用默认值代替。

void TestFunc01(int a = 10, int b = 20){cout << "a + b  = " << a + b << endl;
}
//注意点:
//1. 形参b设置默认参数值,那么后面位置的形参c也需要设置默认参数
void TestFunc02(int a,int b = 10,int c = 10){}
//2. 如果函数声明和函数定义分开,函数声明设置了默认参数,函数定义不能再设置默认参数
void TestFunc03(int a = 0,int b = 0);
void TestFunc03(int a, int b){}int main(){//1.如果没有传参数,那么使用默认参数TestFunc01();//2. 如果传一个参数,那么第二个参数使用默认参数TestFunc01(100);//3. 如果传入两个参数,那么两个参数都使用我们传入的参数TestFunc01(100, 200);return EXIT_SUCCESS;
}

注意点:

5.2  函数的占位参数

c++在声明函数时,可以设置占位参数。占位参数只有参数类型声明,而没有参数名声明。一般情况下,在函数体内部无法使用占位参数。【占位符也是参数,必须传参数】

void TestFunc01(int a,int b,int){//函数内部无法使用占位参数cout << "a + b = " << a + b << endl;
}
//占位参数也可以设置默认值
void TestFunc02(int a, int b, int = 20){//函数内部依旧无法使用占位参数cout << "a + b = " << a + b << endl;
}
int main(){//错误调用,占位参数也是参数,必须传参数//TestFunc01(10,20); //正确调用TestFunc01(10,20,30);//正确调用TestFunc02(10,20);//正确调用TestFunc02(10, 20, 30);return EXIT_SUCCESS;
}

6. 函数重载(overload)

6.1 函数重载概述

    能使名字方便使用,是任何程序设计语言的一个重要特征!

在传统c语言中,函数名必须是唯一的,程序中不允许出现同名的函数。在c++中是允许出现同名的函数,这种现象称为函数重载。

函数重载的目的就是为了方便的使用函数名。

6.2 函数重载基本语法

实现函数重载的条件:

  1. 同一个作用域
  2. 参数个数不同
  3. 参数类型不同
  4. 参数顺序不同
  5. 返回值并不是构成函数重载的条件
//1. 函数重载条件
namespace A{void MyFunc(){ cout << "无参数!" << endl; }void MyFunc(int a){ cout << "a: " << a << endl; }void MyFunc(string b){ cout << "b: " << b << endl; }void MyFunc(int a, string b){ cout << "a: " << a << " b:" << b << endl;}void MyFunc(string b, int a){cout << "a: " << a << " b:" << b << endl;}
}
//2.返回值不作为函数重载依据
namespace B{void MyFunc(string b, int a){}//int MyFunc(string b, int a){} //无法重载仅按返回值区分的函数
}

注意: 函数重载和默认参数一起使用,需要额外注意二义性问题的产生。

为什么函数返回值不作为重载条件呢?

调用准则

#include	<iostream>
using namespace	std;
void	print(double	a) {cout << a << endl;
}
void print(int	a) {cout << a << endl;
}
int	main()
{print(1);	//	print(int)print(1.1);	//	print(double)print('a');	//	print(int)print(1.11f);	//	print(double)return 0;
}

编译器调用重载函数的准则:

6.3 重载底层实现(name mangling)

6.4 函数重载与函数默认参数

6.5 函数重载和函数指针

函数指针基本语法

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>using namespace std;int func(int a, int b)
{cout << "func(int, int)" << endl;return 0;
}int func(int a, int b, int c)
{cout << "func(int, int,int )" << endl;return 0;
}//1 . 定义一种函数类型
typedef int(MY_FUNC)(int, int);//2 顶一个指向之中函数类型的指针类型
typedef int(*MY_FUNC_P)(int, int);int main(void)
{//1.MY_FUNC *fp = NULL;fp = func;fp(10, 20);//2.MY_FUNC_P fp1 = NULL;fp1 = func;fp1(10, 20);//3. int(*fp3)(int, int) = NULL;fp3 = func;fp3(10, 20);func(10, 20);func(10, 20, 30);fp3 = func; //fp3 ---> func(int,int)//实际上在给函数指针赋值的时候,是会发生函数重载匹配的//在调用函数指针的时候,所调用的函数就已经固定了。int(*fp4)(int, int, int) = NULL;fp4 = func; //fp4 ---> func(int,int,int)fp3(10, 30);//func(int,int)fp3(10, 20);fp4(10, 30, 30);return 0;
}

6.6 总结

7.类和对象

7.1 类和对象的基本概念

C和C++中struct区别

  1. c语言struct只有变量
  2. c++语言struct 既有变量,也有函数

访问控制权限

一个类类的内部,是默认private

我们编写程序的目的是为了解决现实中的问题,而这些问题的构成都是由各种事物组成,我们在计算机中要解决这种问题,首先要做就是要将这个问题的参与者:事和物抽象到计算机程序中,也就是用程序语言表示现实的事物。

//封装两层含义
//1. 属性和行为合成一个整体
//2. 访问控制,现实事物本身有些属性和行为是不对外开放
class Person{
//人具有的行为(函数)
public:void Dese(){ cout << "我有钱,年轻,个子又高,就爱嘚瑟!" << endl;}
//人的属性(变量)
public:int mTall; //多高,可以让外人知道
protected:int mMoney; // 有多少钱,只能儿子孙子知道
private:int mAge; //年龄,不想让外人知道
};int main(){Person p;p.mTall = 220;//p.mMoney 保护成员外部无法访问//p.mAge 私有成员外部无法访问p.Dese();return EXIT_SUCCESS;
}

sruct和class的区别

class A{int mAge;
};
struct B{int mAge;
};void test(){A a;B b;//a.mAge; //无法访问私有成员b.mAge; //可正常外部访问
}
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>using namespace std;struct Hero
{char name[64];int sex;
};void printHero(struct Hero& h)
{cout << "Hero" << endl;cout << "name = " << h.name << endl;cout << "sex = " << h.sex << endl;
}class AdvHero
{
public://访问控制权限char name[64];int sex;void printHero(){cout << "advHero" << endl;cout << "name = " << name << endl;cout << "sex = " << sex << endl;}
};class Animal
{//{}以内 叫类的内部, 以外叫类的外部
public:char kind[64];char color[64];//在public下面定义成员变量和函数 是能够在类的内部和外部都可以访问的。void printAnimal(){cout << "kind = " << kind << endl;cout << "color = " << color << endl;}void write(){cout << kind << "开始鞋子了" << endl;}void run(){cout << kind << "跑起来了" << endl;}//
private://在private下面定义的成员变量和方法只能够在类的内部访问};int main(void)
{Hero h;strcpy(h.name, "gailun");h.sex = 1;printHero(h);AdvHero advH;strcpy(advH.name, "ChunBro");advH.sex = 1;advH.printHero();cout << "-----------" << endl;Animal dog;strcpy(dog.kind, "dog");strcpy(dog.color, "yellow");Animal sheep;strcpy(sheep.kind, "sheep");strcpy(sheep.color, "white");dog.write();sheep.run();return 0;
}

将成员变量设置为private

class AccessLevels{
public://对只读属性进行只读访问int getReadOnly(){ return readOnly; }//对读写属性进行读写访问void setReadWrite(int val){ readWrite = val; }int getReadWrite(){ return readWrite; }//对只写属性进行只写访问void setWriteOnly(int val){ writeOnly = val; }
private:int readOnly; //对外只读访问int noAccess; //外部不可访问int readWrite; //读写访问int writeOnly; //只写访问
};

7.2 用class去封装带行为的类

class 封装的本质,在于将数据和行为,绑定在一起然后能过对象来完成操 作。

#include	<iostream>
using namespace	std;
class	Date
{
public:void	init(Date & d);void	print(Date& d);bool	isLeapYear(Date& d);
private:int	year;int	month;int	day;
};
void	Date::init(Date& d)
{cout << "year,month,day:" << endl;cin >> d.year >> d.month >> d.day;
}
void	Date::print(Date& d)
{cout << "year	month	day" << endl;cout << d.year << ":" << d.month << ":" << d.day << endl;
}
bool	Date::isLeapYear(Date& d)
{if ((d.year % 4 == 0 && d.year % 100 != 0) || d.year % 400 == 0)return true;elsereturn false;
}
int	main()
{Date	d;d.init(d);d.print(d);if (d.isLeapYear(d))cout << "leap	year" << endl;elsecout << "not	leap	year" << endl;return 0;
}

7.3 类的封装

一般类中的属性是private

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>using namespace std;struct Date
{int year;int month;int day;
};void init_date(struct Date & d)
{cout << "year, month, day" << endl;cin >> d.year;cin >> d.month;cin >> d.day;
}//打印data的接口
void print_date(struct Date &d)
{cout << d.year << "年" << d.month << "月" << d.day << "日" << endl;
}bool is_leap_year(struct Date &d)
{if (((d.year % 4 == 0) && (d.year % 100 != 0)) || (d.year % 400 == 0)) {return true;}return false;
}class MyDate
{
public://成员方法 成员函数void init_date(){cout << "year, month, day" << endl;cin >> year;cin >> month;cin >> day;}//打印data的接口void print_date(){cout << year << "年" << month << "月" << day << "日" << endl;}bool is_leap_year(){if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) {return true;}return false;}int get_year(){return year;}void set_year(int new_year){year = new_year;}protected://保护控制权限。在类的继承中跟private有区别,在单个类中,跟private是一抹一样。
private:int year;int month;int day;
};//一个类类的内部,默认的访问控制权限是private
class Hero
{int year;
};//一个结构体默认的访问控制权限的是public
struct Hero2
{int year;void print(){}
};int main(void)
{
#if 0Date d1;init_date(d1);print_date(d1);if (is_leap_year(d1) == true) {cout << "是闰年 " << endl;}else {cout << "不是闰年 " << endl;}
#endifMyDate my_date;my_date.init_date();my_date.print_date();if (my_date.is_leap_year() == true){cout << "是闰年 " << endl;}else {cout << "不是闰年 " << endl;}//getter,settercout << my_date.get_year() << endl;my_date.set_year(2000);cout << my_date.get_year() << endl;Hero h;//h.year = 1000;Hero2 h2;h2.year = 100;return 0;
}

7.4 ⾯向对象编程

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>using namespace std;//面向对象
class Dog
{
public:void eat(char *food){cout << name << "吃" << food << endl;}char name[64];
};//面向过程
void eat(class Dog &dog, char *food)
{cout << dog.name << "吃" << food << endl;
}int main(void)
{Dog dog;strcpy(dog.name, "狗");eat(dog, "翔");dog.eat("翔");return 0;
}

 求圆的面积和周长

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>using namespace std;//圆的周长
double getCircleGirth(double r)
{return 2 * 3.14 * r;
}//源的面积
double getCircleArea(double r)
{return 3.14 * r * r;
}//用面向对象实现//圆类
class Circle
{
public:void setR(double r){m_r = r;}double getR(){return m_r;}double getGirth(){return 2 * 3.14 * m_r;}double getArea(){return m_r * m_r * 3.14;}private:double m_r; //圆的私有成员 半径
};class Circle2
{
public:void setR(double r){m_r = r;}double getR(){return m_r;}double getArea(){m_area = m_r * m_r * 3.14;return m_area;}double getGirth(){m_girth = m_r * 2 * 3.14;return m_girth;}private:double m_r;double m_girth; //周长double m_area;//面积
};int main(void)
{double r = 10; //圆的半径double g = 0;double a = 0;g = getCircleGirth(r);a = getCircleArea(r);cout << "圆的半径是" << r << endl;cout << "圆的周长是" << g << endl;cout << "圆的面积是" << a << endl;cout << "------" << endl;Circle c;c.setR(10);cout << "圆的半径是" << c.getR() << endl;cout << "圆的周长是" << c.getGirth() << endl;cout << "圆的面积是" << c.getArea() << endl;cout << "------------" << endl;Circle2 c2;c2.setR(10);cout << "圆的半径是" << c2.getR() << endl;cout << "圆的周长是" << c2.getGirth() << endl;cout << "圆的面积是" << c2.getArea() << endl;return 0;
}

圆的周长和面积多文件编写

Circle.h

#pragma once#if 0
#ifndef __CIRCLE_H_
#define __CIRCLE_H_#endif
#endifclass Circle
{
public://设置半径:void setR(double r);//得到半径double getR();double getArea();double getGirth();private:double m_r;double m_area;double m_girth;
};

Circle.cpp

#include "Circle.h"//Circle::表示还在圆的内部
void Circle::setR(double r)
{m_r = r;
}double Circle::getR()
{return m_r;
}double Circle::getArea()
{m_area = m_r *m_r *3.14;return m_area;
}double Circle::getGirth()
{m_girth = m_r * 2 * 3.14;return m_girth;
}

mian.cpp

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>#include "Circle.h"using namespace std;int main(void)
{Circle c;c.setR(10);cout << "面积" << c.getArea() << endl;return 0;
}

判断两个立方体是否相等

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>using namespace std;//立方体类
class Cube
{
public:void setABC(int a, int b, int c){m_a = a;m_b = b;m_c = c;}int getArea(){return (m_a*m_b) * 2 + (m_a*m_c) * 2 + (m_b*m_c) * 2;}int getVolume(){return (m_a*m_b*m_c);}int getA(){return m_a;}int getB(){return m_b;}int getC(){return m_c;}//同类之间无私处bool judgeCube(Cube &another){if (m_a == another.m_a &&m_b == another.getB() &&m_c == another.getC()) {return true;}else {return false;}}
private:int m_a;int m_b;int m_c;
};//全局函数
bool judgeCube(Cube &c1, Cube &c2)
{if (c1.getA() == c2.getA() &&c1.getB() == c2.getB() &&c1.getC() == c2.getC()) {return true;}else {return false;}
}int main(void)
{Cube c1;c1.setABC(10, 20, 30);Cube c2;c2.setABC(10, 20, 30);cout << "c1 的体积是" << c1.getVolume() << endl;cout << "c1 的面积是" << c1.getArea() << endl;if (judgeCube(c1, c2) == true) {cout << "相等" << endl;}else {cout << "不相等" << endl;}cout << " ------ " << endl;if (c1.judgeCube(c2) == true) {cout << "相等" << endl;}else {cout << "不相等" << endl;}return 0;
}

判断点是否在圆的内部

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>using namespace std;//点类
class Point
{
public:void setXY(int x, int y){m_x = x;m_y = y;}int getX(){return m_x;}int getY(){return m_y;}
private:int m_x;int m_y;
};//圆类
class Circle
{
public:void setXY(int x, int y){x0 = x;y0 = y;}void setR(int r){m_r = r;}//提供一个判断点是否在圆内//true 在内部//false 在外部bool judgePoint(Point &p){int dd;dd = (p.getX() - x0)*(p.getX() - x0) + (p.getY() - y0)*(p.getY() - y0);if (dd > m_r*m_r) {return false;}else {return true;}}private:int x0;int y0;int m_r;
};int main(void)
{Circle c;c.setXY(2, 2);c.setR(4);Point p;p.setXY(8, 8);if (c.judgePoint(p) == true) {cout << "圆的内部" << endl;}else {cout << "圆的外部" << endl;}return 0;
}

判断两个圆是否相交

#include<iostream>
using namespace std;
class Point {
public:void setXY(int x, int y) {m_x = x;m_y = y;}//计算两个点之间的距离double pointDistance(Point& another) {int dis_x = m_x - another.m_x;int dis_y = m_y - another.m_y;//斜边double dis = sqrt(dis_x * dis_x + dis_y * dis_y);return dis;}private:int m_x;int m_y;
};
class Circle {
public:void setR(int r) {m_r = r;}void setXY(int x1, int y1) {p0.setXY(x1, y1);}//判断圆是否相交bool isConnection(Circle& another) {//两个圆的半径之和int r = m_r + another.m_r;//两个圆心之间的距离double dis = p0.pointDistance(another.p0);if (dis <= r) {			//相交return true;}else {return false;}}private:int m_r;Point p0;
};int main(void)
{Circle c1, c2;int x, y, r;cout << "请输入第一个圆的半径" << endl;cin >> r;c1.setR(r);cout << "请输入第一个圆的x" << endl;cin >> x;cout << "请输入第一个圆的y" << endl;cin >> y;c1.setXY(x, y);cout << "请输入第2个圆的半径" << endl;cin >> r;c2.setR(r);cout << "请输入第2个圆的x" << endl;cin >> x;cout << "请输入第2个圆的y" << endl;cin >> y;c2.setXY(x, y);if (c1.isConnection(c2) == true) {cout << "相交" << endl;}else {cout << "不想交" << endl;}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/84900.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

springboot整合返回数据统一封装

1、MagCode&#xff0c;错误码枚举类 package com.mgx.common.enums;import lombok.*; import lombok.extern.slf4j.Slf4j;/*** 错误码* author mgx*/ Slf4j NoArgsConstructor AllArgsConstructor public enum MsgCode {/*** 枚举标识&#xff0c;根据业务类型进行添加*/Code…

PostgreSQL 数据库实现公网远程连接

文章目录 前言1. 安装postgreSQL2. 本地连接postgreSQL3. Windows 安装 cpolar4. 配置postgreSQL公网地址5. 公网postgreSQL访问6. 固定连接公网地址7. postgreSQL固定地址连接测试 前言 PostgreSQL是一个功能非常强大的关系型数据库管理系统&#xff08;RDBMS&#xff09;,下…

建议收藏《Verilog代码规范笔记_华为》(附下载)

华为verilog编程规范是坊间流传出来华为内部的资料&#xff0c;其贴合实际工作需要&#xff0c;是非常宝贵的资料&#xff0c;希望大家善存。至于其介绍&#xff0c;在此不再赘述&#xff0c;大家可看下图详细了解&#xff0c;感兴趣的可私信领取《Verilog代码规范笔记_华为》。…

IDEA开发工具技巧

1.1 IDEA相关插件 idea插件下载地址&#xff1a;https://plugins.jetbrains.com/ 开发必装插件&#xff1a; &#xff08;1&#xff09; 快速查找api接口 RestfulTool 插件&#xff0c;推荐指数⭐⭐⭐⭐⭐ [RestfulTool搜索插件使用详解](https://blog.csdn.net/weixin_450147…

Spring学习笔记2 Spring的入门程序

Spring学习笔记1 启示录_biubiubiu0706的博客-CSDN博客 Spring官网地址:https://spring.io 进入github往下拉 用maven引入spring-context依赖 写spring的第一个程序 引入下面依赖,好比引入Spring的基本依赖 <dependency><groupId>org.springframework</groupId&…

医学影像信息(PACS)系统软件源码

PACS系统是PictureArchivingandCommunicationSystems的缩写&#xff0c;与临床信息系统&#xff08;ClinicalInformationSystem,CIS&#xff09;、放射学信息系统(RadiologyInformationSystem,RIS)、医院信息系统(HospitalInformationSystem,HIS)、实验室信息系统&#xff08;L…

CentOS 7 安装Libevent

CentOS 7 安装Libevent 1.下载安装包 新版本是libevent-2.1.12-stable.tar.gz。&#xff08;如果你的系统已经安装了libevent&#xff0c;可以不用安装&#xff09; 官网&#xff1a;http://www.monkey.org/~provos/libevent/ 2.创建目录 # mkdir libevent-stable 3.解压 …

MES管理系统在生产中的应用及智能工厂的构建思路

在当今制造业中&#xff0c;随着信息化技术和智能化的不断发展&#xff0c;MES生产管理系统已成为工厂生产的核心组成部分。MES管理系统不仅能够提高生产效率&#xff0c;还可以优化生产流程&#xff0c;提升产品质量。本文将详细介绍MES管理系统在工厂生产中的应用以及构建智能…

Windows AD 组策略 关闭自动更新

1、创建组策略 2、配置 计算机配置 → 策略 → 管理模板 → Windows 组件 → Windows 更新 &#xff08;1&#xff09;禁止 配置自动更新 &#xff08;2&#xff09;启用 "删除使用所有Windows更新功能的访问权限" 3、客户机 更新组策略

Webpack打包时Bable解决浏览器兼容问题

当我们使用js新特性语法编写代码时&#xff0c;在旧的浏览器中兼容性并不好。但是我们希望能够在旧浏览器中使用这些新特性。 使用babel可以使js新代码转换为js旧代码&#xff0c;增加浏览器的兼容性。 如果我们希望在Webpack中支持babel&#xff0c;则需要在Webpack中引入bab…

MySQL 学习笔记(基础)

首先解释数据库DataBase&#xff08;DB&#xff09;&#xff1a;即存储数据的仓库&#xff0c;数据经过有组织的存储 数据库管理系统DataBase Management System&#xff08;DBMS&#xff09;&#xff1a;管理数据库的软件 SQL&#xff08;Structured Query Language&#xf…

47个Docker常见故障的原因和解决方式

本文针对Docker容器部署、维护过程中&#xff0c;产生的问题和故障&#xff0c;做出有针对性的说明和解决方案&#xff0c;希望可以帮助到大家去快速定位和解决类似问题故障。 Docker是一种相对使用较简单的容器&#xff0c;我们可以通过以下几种方式获取信息&#xff1a; 1、…

2023华为杯E题:出血性脑卒中临床智能诊疗建模(不断更新)

文章目录 一、 背景介绍二、 数据集介绍及建模目标第一题&#xff1a;血肿扩张风险相关因素探索建模。第一问要求第一问解题思路第二问第二问解体思路 第二题&#xff1a;血肿周围水肿的发生及进展建模&#xff0c;并探索治疗干预和水肿进展的关联关系第一问第一问思路第二问第…

LeetCode 847. Shortest Path Visiting All Nodes【状态压缩,BFS;动态规划,最短路】2200

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…

【Android知识笔记】进程通信(三)

在上一篇探索Binder通信原理时,提到了内存映射的概念,其核心是通过mmap函数,将一块 Linux 内核缓存区映射到一块物理内存(匿名文件),这块物理内存其实是作为Binder开辟的数据接收缓存区。这里有两个概念,需要理解清楚,那就是操作系统中的虚拟内存和物理内存,理解了这两…

零基础学前端(五)HTML+CSS实战:模仿百度网站首页

1. 该篇适用于从零基础学习前端的小白 2. 初学者不懂代码得含义也要坚持模仿逐行敲代码&#xff0c;以身体感悟带动头脑去理解新知识 一、实战&#xff1a;将百度网站首页补全 上一篇零基础学前端&#xff08;三&#xff09;重点讲解 HTML-CSDN博客我们已经将顶部两侧内容已经…

无聊的一篇博客(如何通过路由器登陆页对固定机器进行网速干扰,如何帮熊孩子戒网瘾)

1. 路由器登陆页面&#xff0c;按钮解析&#xff0c;获取按钮。 2. JavaScript与上传的脚本。 // 获取要点击的按钮A和按钮B元素var isRunning true; // 初始状态为false// 定义一个函数来模拟点击按钮A和按钮B function clickButtons() {if (isRunning) {// 随机生成一个延时…

03.Qt信号槽使用及其原理

一、QT信号槽概念原理讲解 信号槽 类似windows的消息机制信号函数&#xff0c;只发送不需要知道接收者槽函数&#xff08;普通函数&#xff09;&#xff0c;只接收不管通信QObject来绑定 Qt信号槽原理 绑定信号函数和槽函数调用信号函数&#xff08;将信号写入队列&#xf…

理解Nginx反向代理详解

什么是Nginx反向代理&#xff1f; Nginx是一个高性能的开源Web服务器&#xff0c;但它也可以用作反向代理服务器。反向代理是一种服务器配置&#xff0c;它允许Nginx接收客户端请求&#xff0c;然后将这些请求转发到后端服务器&#xff0c;最终将响应返回给客户端。这种配置对于…

CSS 模糊效果 CSS 黑白效果 CSS调整亮度 对比度 饱和度 模糊效果 黑白效果反转颜色

CSS 模糊效果 CSS 黑白效果 CSS调整亮度 饱和度 模糊效果 黑白效果 实现 调整亮度 饱和度 模糊效果 黑白效果 使用 filter1、模糊2、亮度3、对比度4、饱和度5、黑白效果6、反转颜色7、组合使用8、 filer 完整参数 实现 调整亮度 饱和度 模糊效果 黑白效果 使用 filter 1、模糊…