C++学习笔记!

这是刚开始写的文件,后来发现太大不合适就开始分开写了

#include<iostream>
#include<string>//c++风格字符串头文价
//下面是定义宏常量:宏常量一旦定下,下文就不能修改了
#define day 7
using namespace std;
int add(int a, int b)
{
	int sum = a + b;
	return sum;//即最终函数的值为sum,就相当于y
}

int main()
{

	//这是单行注释
	/*这是多行注释,可以将多行的信息变为注释*/
	/*main是一个函数的入口
	每个程序有且仅有一个main函数
	*/
	cout << "hello C++" << endl;
	cout << "一周总共有" << day << "天" << endl;
	int a = 10;//与c语言一致,这就是创建变量
	cout << "a=" << a << endl;

	//如果我用int函数,则变量值是可修改的,但用了const就不行了
	int b= 5;
	b = 6;
	cout << b << endl;
	short t = 1;//短整型(-32768~32767)
	int  w = 2;//整型(-2^31---2^31-1)
	long z = 3;//长整型(数的范围与整型一致)
	long long f = 4;//长长整型(-2^63----2^63-1)
	//float 4字节,doule 8字节
	cout << sizeof(f) << endl;//利用sizeof求出数据占用内存
	cout << f << endl;
	char ch = 'a';
	cout << (int)ch << endl;//输出字符的大小
	cout << "//" << endl;//与c语言一致,需要加个/来输出后面的/
	/*“/t”水平制表符,占8个空间,aaa/t则输出aaa加八个空格
	,aaaaa/t则输出aaaaa加三个空格*/
	cout << "aaa\tHello,world" << endl;
	cout << "aaaaa\tHello,world" << endl;		
	//接下来是字符串 C语言风格
	char str[] = "hello,world";//注意要有[],这标志这是字符串,同时用“”
		//接下来是c++风格字符串(需要先设头文件)见开头
		string str2 = "hello,world";
		cout << str2 << endl;
	//bool类型判断真假
	bool flag = true;//输出1
	cout << flag << endl;
	flag = false;
	cout << flag << endl;


		/*cout << b << endl;
	cout << a+b<< endl;*/
	/*const int c = 12;
	c = 13;*/
	//上面这行就会报错!!
	/*数据类型(eg.整型,字符型···)类型不同,对变量
	的内存也不同*/
	
	//利用cin>>来从键盘上输入数据
	//在c++中,两个整数相除,结果为整数(取整)eg.10/3=3
	//两个小数无法做取余运算
	//a%=b<==>a=a%b
	int j = 0;
	cin >> j;
	cout << j << endl;
	//以下是多条件if语句:
	/*接下来是我写的一个例子:
	输入高考分数,如果大于600,输出“考上一本大学”,如果大于五百
	,则输出考上二本大学,如果大于400,输出考上三本大学,否则,
	输出未考上!*/


	cout << "请输入高考分数" << endl;
	int i = 0;
	cin >> i;
	if (i > 600)
	{
		cout << "考上一本大学" << endl;//如果不满足i > 600,则执行下一个else if

	}
	else if (i > 500)
	{
		cout << "考上二本大学" << endl;//如果不满足,继续往下执行

	}
	else if (i > 400)
	{
		cout << "考上三本大学" << endl;//如果都不满足,则执行else

	}
	else
	{
		cout << "你没考上大学" << endl;
	}
	//项目练习:三只小猪称体重
	//猜数字
	//找水仙花数

	int arr1[];//注意:定义数组时,应有长度,像这个就会报错(不允许使用不完整的类型)
	int arr2[] = { 1,2,3.4 };//这个就没问题
	cout<< (int)arr2 << endl;//这样输出arr2的地址
	cout << (int)arr2[0] << endl;//与上相同
	/*数组的地址与数组第一个元素的地址相同*/
	cout << sizeof(arr2) << endl;//arr2的大小
	//数组名是常量,不能修改,即:arr2 = 100;这样是不对的


	/*二位数组的四种定义方式:
    1.数据类型 数组名[行数][列数];
    2.数据类型 数组名[行数][列数]={{数据1,数据2},{数据3,数据4}};
	3.数据类型 数组名[行数][列数]={数据1,数据2,数据3,数据4}(利用给出
	行数列数电脑自动分配)
	4.数据类型 数组名[  ][列数]={数据1,数据2,数据3,数据4};
	*/

	//二维数组查看占用内存大小:
	int arr[2][3] =
	{
		{1,2,3},
		{4,5,6}
	};
	cout << sizeof(arr) << endl;//查看数组占用内存大小
	cout << sizeof(arr[0]) << endl;//查看第一行占用内存
	cout << sizeof(arr[0][0]) << endl;//第一个数据算占用内存
	cout << arr << endl;//查看数组的首地址,即第一行的地址,及第一个数据的首地址

//接下来是函数
	/*返回值类型  函数名 (参数列表)
	*   int        add   (int num1,int num2)
	* {
	* 
	*   函数体语句
	*   
	* 
	*   return表达式
	* 
	* }
	* 
	*/
	//例如max函数,可以见typora笔记





	system("pause");//这是按任意键继续的功能

	int a = 10;
	int b = 20;
	//a和b在上面确实出现了,下面函数用到了,因此被称为 实际参数,简称实参
	//而在函数定义的时候,num1,num2并没有真实的数据,只是形式上的参数,因此被称为形参
	//当调用函数时,实参的值会传递给形参
	int c = add(a, b);
	return 0;

	//值传递建一个新的c++例子


	//函数的几种常见的样式:看新文件


}
//

接下来是函数

#include<iostream>
using namespace std;
//函数的分文件编写见新文件
//接下来介绍函数的几种常见样式:

//1.无参无返
void test01()
{
	//void a = 10;这样会报错,无类型不可以创建变量,原因无法分配内存
	cout << "this is test01" << endl;
	//test01();函数调用
}

//2.有参无返
void test02(int a)
{
	cout << "this is test02 a=" << a << endl;
	//调用时的注意事项见后
}
//3.无参有返
int test03()
{
	cout << "this is test03" << endl;

	return 1000;//test03的值变为1000

}
//4.有参有反
int max(int a, int b)
{
	if (a > b)
		return a;
	else
		return b;

	//下面是个简单写法
	// return a>b? a:b;
}

//接下来是函数的声明
//在这先声明一个函数,然后把自己写的这个函数放在最后
int min(int a, int b);
//声明可以写多次,但定义只能写一次,如下:
int min(int a, int b);
int min(int a, int b);
int min(int a, int b);
int main()
{
	//接下来是函数的调用


	//1。
	test01();
	//2.
	test02(100);//这时候就要给这个形参赋值了
	//3.
	int num1 = test03();
	cout << "num1 = " << num1 << endl;
	//4.
	int a, b, c;
	a = 1;b = 2;
	c = max(a, b);
	cout << c << endl;

	system("pause");
	return 0;


}

//在这写min函数
int min(int a, int b)
{
	if (a > b)
		return b;
	else
		return a;
}

形参与实参的了解

#include<iostream>
using namespace std;

//接下来做个交换函数,讲个值传递的例子
void swap(int num1, int num2)//不需要返回某个值时,即最终不需要输出什
//可以利用void,这样就不用写return;了
{
	cout << "交换前" << endl;
	cout << "num1=" <<num1<< endl;
	cout << "num2=" << num2<<endl;

	int temp = num1;
	num1 = num2;
	num2 = temp;

	cout << "交换后" << endl;
	cout << "num1=" <<num1<< endl;
	cout << "num2=" << num2<<endl;


	
}


int main()
	{
	int a = 10;
	int b = 20;

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

	//注意输出结果,当我们做值传递时,函数的形参发生改变,并不会影响实参
	//即最后a还是a,b还是b,值并不会发生改变

	swap(a, b);

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

	system("pause");
	return 0;


}

函数的递归调用

定义:函数直接或间接的调用自身叫做函数的调用
递归三要素:
1.解决问题相似性--->eg.求n的阶乘,从n到1
2.终止条件:必须让他停下来,不能无限制执行,例如阶乘到1就结束了
3.渐进性:n——>n-1——>n-2——>……要有规律
常见的例题就是汉诺塔问题

接下来是函数的分文件编写

C++学习笔记-小白菜博客
在这里插入图片描述

在这里插入图片描述

接下来是指针

#include<iostream>
using namespace std;

void swap01(int a, int b)
{
int temp = a;
a = b;
b = temp;
}

//地址传递:通过形参改变实参a,b的值
void swap02(int* p1, int* p2)
{
	int temp = *p1;
	*p1 = *p2;
	*p2 = temp;
/*
* 用指针,即通过指针来改变对应地址里的值,进而真正改变a,b中所存的值
* 这的实参是指针,因此只是指针所指的地址没有发生改变
*/
}
int main()
{
	//接下来是指针
	//指针的占用字节大小确定,在32位系统中为4个字节,在64位系统中为8字节
	//这个64为系统环境与32为系统环境,可在上方本地windows调试器左边的x64(64位),x86(32位)里选
	int a = 0;
	int b = 2;
	int* p = &a;//int *p,即为定义整型指针,&为取地址符,指针就是地址
	//指针同样包含值与地址两部分
	*p = 1000;//这是通过指针直接对其所对应的地址上的值进行修改,* 为 解引用

	cout << *p << endl;

	//下面是空指针
	int* p1 = NULL;    //指针变量指向内存地址编号为0的空间
		//这就是初始化指针   注:空指针指向的内存是不可以访问的
	//原因:0~255内存编号是系统占用的,因此不可以访问(不能对其修改:eg. *p1 = 1000;)



	//接下来是野指针
	//指 指针变量指向非法的内存空间

	//int* p2 = 0x1100;  //这样会报错,0x1100是个具体的数,不是个地址,要修改为地址有以下操作
	//int* p2 = (int*)0x1100; //这就是指向一个地址      随便拿一指针指向随便一个地址,无法访问
    
	//  cout << *p2 << endl; //这叫读取访问权限冲突

	//const修饰指针 ----常量指针:指针的指向可以修改,但是指针指向的常量无法修改

	const int* p3 = &a;
	p3 = &b;//可以这样改,但不能*p3 = 23

	//const修饰变量 ====指针常量 :指针指向不可改,但其指向的值可修改

	int* const p4 = &a;//这就是指针常量,注意事项不再赘述
	
	//const既修饰指针,又修饰常量

	const int* const p5 = &a;//这是指向和指向的量都不能修改的

	
	
	//*: 指针 const: 常量
	//记法:const *,(*为常量)则*p = ··这种操作无法进行  *const p,则 p = &a 这种操作无法进行
	

	//接下来是 指针与数组

	int arr[10] = { 1,2.3,4,5,6,7,8,9,10 };
	cout << "The first element is:" << arr[0] << endl;

	int* p6 = arr;//arr就是数组首地址  =  &arr[0]

	cout << "using pointer to the first element:" << *p6 << endl;

	p6++;   //对指针进行加减是对其指向的元素类型进行加减。计算单位不是字节,是其指向的元素类型
	      //p++,p--,p+i,p-i,p+=i,p-=i;
          //若p1与p2指向同一数组,则p1-p2 = 两指针间元素个数 <=> (p1-p2)/d 
	      //p1+p2   无意义

    // 一维数组万能公式:  a[i] = *(a+i)    因此有  a[3] = *(a+3) = *(3+a) = 3[a]   这个公式很攒劲    
	cout << "using pointer to the second element:" << *p6 << endl;


	//下面是指针与函数   地址传递
	// 以c语言为例
	/*
	// #include<stdio.h>
#define SIZE 5
	void change(int a[5])    //这个地方传递的是数组首地址,不是数组 
	{             //a[5] 可以写成*a,因为它本身就是个地址! 
		a[3] = 100;    //这个a[3]本质上也是个地址,利用全能公式可以得到 
	}
	int main()
	{
		int a[SIZE], i;
		for (i = 0;i < SIZE;i++)
			a[i] = i + 1;
		change(a);
		for (i = 0;i < SIZE;i++)
			printf("%d\t", a[i]);

		return 0;
	}
	*/ 

	//int *p;
	//p[i] = *(p+i)
	//&p[i] = &(*(p+i))    万能公式
	//      = p+i




	//将形参中的改变的值带给实参中
	
	//见 swap02函数

	




	system("pause");
	return 0;

}
#include<iostream>
using namespace std;
///*冒泡法排序:
//	1.比较相邻的两个元素,如果第一个大于第二个,则交换他们两个
//	2.对每一对相邻元素做同样的工作,执行完毕后,找出一个最大值
//	3.重复以上的步骤,每次比较次数-1,直到不需要比较*/
//
//int arr[] = { 4,2,8,0,5,7,1,3,9 };
//int i;
//for (int j = 0;j < 9;j++)
//{
//	cout << arr[j] << endl;
//}
//cout << endl;
//for (int h = 0;h < 8;h++) {
//
//	for (i = 0;i < 8;i++)//只写着一个循环的话第一个与第二个
//		//换,第二个与第三个换,第三个与第四个换,但第二个
//		//就不会与第三个比较了,因此要从头再重新比较一遍!
//	{
//		int temp = 0;
//		if (arr[i] > arr[i + 1])
//		{
//			temp = arr[i + 1];
//			arr[i + 1] = arr[i];
//			arr[i] = temp;
//		}
//	}
//}
//for (int j = 0;j < 9;j++)
//{
//	cout << arr[j] << endl;

//冒泡排序函数
void bubble_sort(int* arr, int len)//这就是 指针数组 这个概念了,arr[i]在这为指针数组,对应每一项的地址
{
	for (int i = 0; i < len; i++)
	{
		for(int j = 0;j<len-i-1;j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}

}


//打印函数
void print_array(int* arr, int len)
{
	for (int i = 0;i < len;i++)
	{
		cout << arr[i] << endl;
	}
}

int main()
{

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

	bubble_sort(arr, 10);
	print_array(arr, 10);




	system("pause");
	return 0;
}

类和对象

  include<iostream>
#include<string>	// 定义字符串变量需要这个头文件
using namespace std;
class Circle        //定义个圆类
{
	//访问权限:

public:        //以下是公共权限
	//属性:
	int m_r;     //半径


	//行为:
	double Circumference()           // 这里面不用传参
	{
		return 2 * m_r * 3.1415926;
	}
};      //注意这有分号
class Student
{
public:
	string name;
	int stu_num;
void setName(string name1)    //通过行为给姓名赋值
	{
		name = name1;
		cout << name << endl;    
	}

};
int main()
{
	//下面是个圆
	Circle r1;    //通过一个类,创建一个对象的过程
	r1.m_r = 2;    
	cout << r1.Circumference() << endl;
	
	//下面是一个学生类
	Student xiaoming;
	xiaoming.name = "xiaoming";
        xiaoming.setName("xiaoming");  //这是通过行为给姓名赋值
	xiaoming.stu_num = 202021515;
	cout << xiaoming.name<<"\n" << xiaoming.stu_num << endl;
}

访问权限

三种访问权限:
公共权限 public :成员类内可以访问,类外可以访问
保护权限 protected :成员类内可以访问,类外不能访问 子类也可以访问父类中的保护内容
私有权限 private :成员类内可以访问,类外不能访问 对于私有权限,子类依然无法访问

struct和class的区别

struct 与 class 的唯一区别就是默认的访问权限不同
class C1
{
int m_A; //默认为私有权限
};
class C2
{
int m_B; //默认为公共权限

具体案例:
class Person //设置一个私有权限,并通过公共函数来对其进行读写
{
public:
void fixName(string name)
{
p_name = name;
}
void getName() //可读可写
{
cout << p_name << endl;
}

int  getAge()
{
	p_age = 18;
	return p_age;
}
    void setAge(int age)     //如果要对年龄进行可写操作,如下:
{
	if (age < 0 || age >150)
	{
		p_age = 0;
		cout << "你修仙了吗?" << endl;
			return;            //这个就是如果不符合条件,直接跳出函数!!
	}
	p_age = age;
}
    void setAge(int age)
    {
           
void lover(string loveer)
{
	p_lover = loveer;
}

private:
string p_name; //姓名,可读可写
int p_age; //年龄,只读
string p_lover; //情人,只写
};
以下是main:
Person p1;
p1.lover("张三");
p1.fixName("小王");
p1.getName();
p1.setAge(18);

案例:

  • 定义个立方体类
#include<iostream>
using namespace std;

//有关类的函数不能写在前面,这时候他还不知道这个Cube是什么

class Cube
{
public:
	//长
	void seta(int l)
	{
		a = l;
	}

	int geta()
	{
		return a;
	}
	//宽
	void setb(int l)
	{
		b = l;
	}

	int getb()
	{
		return b;
	}
	//高
	void setc(int l)
	{
		c = l;
	}

	int getc()
	{
		return c;
	}

	bool Equal(Cube& c2)   //定义在类里的函数:成员函数    注意形参的形式
		//Cube& c2 与Cube &c2都行, 

		 //注意,这里传参只需要在传入一个参数即可,在使用时c1.Equal(...)即可

	{
		if (c2.a == a && c2.b == b && c2.c == c)  //因为是在类内,所以直接可以用c
			return 1;
		else
			return 0;
	}

private:
	int a;    //长
	int b;    //宽
	int c;    //高

};
bool equal(Cube &c1, Cube &c2)      //比较两个立方体,看看是否相等
//这是全域函数,上一个是定义在类里面的
{
	if (c1.geta() ==c2.geta()&& c1.getb() == c2.getb() && c1.getc() == c2.getc())
	{
		return 1;
	}
	else
		return 0;
}

int main()
{
	Cube c1;
	c1.seta(5);
	c1.setb(5);
	c1.setc(5);
	cout << c1.geta()<<endl << c1.getb()<<endl << c1.getc() << endl;
	Cube c2;
	c2.seta(5);
	c2.setb(5);
	c2.setc(5);

	if (equal(c1, c2))
		cout << "两个相等" << endl;
	else
		cout << "两个不相等" << endl;
	if(c1.Equal(c2))
		cout << "两个相等" << endl;
	else
		cout << "两个不相等" << endl;

	system("pause");
	return 0;
}

友元函数

知识来源[菜鸟教程]https://www.runoob.com/cplusplus/cpp-friend-functions.html

  • 类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数。
    友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类,在这种情况下,整个类及其所有成员都是友元。
    如果要声明函数为一个类的友元,需要在类定义中该函数原型前使用关键字 friend,如下所示:
class Box
{
   double width;
public:
   double length;
   friend void printWidth( Box box );
   void setWidth( double wid );
};
  • 声明类 ClassTwo 的所有成员函数作为类 ClassOne 的友元,需要在类 ClassOne 的定义中放置如下声明:
class Classone
{
double width;
public:
    double lenth;
    friend class Classtwo;
};
class Classtwo
{
double high;
};

接下来是具体例子

#include <iostream>

using namespace std;

class Box
{
    double width;
public:
    friend void printWidth(Box box);
    friend class BigBox;
    void setWidth(double wid);
};

class BigBox
{
public :
    void Print(int width, Box &box)
    {
        // BigBox是Box的友元类,它可以直接访问Box类的任何成员
        box.setWidth(width);
        cout << "Width of box : " << box.width << endl;
    }
};

// 成员函数定义
void Box::setWidth(double wid)
{
    width = wid;
}

// 请注意:printWidth() 不是任何类的成员函数
void printWidth(Box box)
{
    /* 因为 printWidth() 是 Box 的友元,它可以直接访问该类的任何成员 */
    cout << "Width of box : " << box.width << endl;
}

// 程序的主函数
int main()
{
    Box box;
    BigBox big;

    // 使用成员函数设置宽度
    box.setWidth(10.0);

    // 使用友元函数输出宽度
    printWidth(box);

    // 使用友元类中的方法设置宽度
    big.Print(20, box);

    getchar();
    return 0;
}

[重载函数与重载运算符]https://www.runoob.com/cplusplus/cpp-overloading.html

  • 重载:同一作用域中的某个函数和运算符指定多个定义,使用时交给编译器选择合适的定义。
  • 重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明,但是它们的参数列表和定义(实现)不相同。
  • 当您调用一个重载函数或重载运算符时,编译器通过把您所使用的参数类型与定义中的参数类型进行比较,决定选用最合适的定义。选择最合适的重载函数或重载运算符的过程,称为重载决策。

函数重载:

同一个作用域内,可以声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或者顺序)必须不同。您不能仅通过返回类型的不同来重载函数。
下面的实例中,同名函数 print() 被用于输出不同的数据类型:

#include <iostream>
using namespace std;
 
class printData
{
   public:
      void print(int i) {
        cout << "整数为: " << i << endl;
      }
 
      void print(double  f) {
        cout << "浮点数为: " << f << endl;
      }
 
      void print(char c[]) {
        cout << "字符串为: " << c << endl;
      }
};
 
int main(void)
{
   printData pd;
 
   // 输出整数
   pd.print(5);
   // 输出浮点数
   pd.print(500.263);
   // 输出字符串
   char c[] = "Hello C++";
   pd.print(c);
 
   return 0;
}

运行结果

整数为: 5
浮点数为: 500.263
字符串为: Hello C++

重载运算符

  • 您可以重定义或重载大部分 C++ 内置的运算符。这样,您就能使用自定义类型的运算符。
  • 重载的运算符是带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的。与其他函数一样,重载运算符有一个返回类型和一个参数列表。
Box operator+(const Box&);

声明加法运算符用于把两个 Box 对象相加,返回最终的 Box 对象。大多数的重载运算符可被定义为普通的非成员函数或者被定义为类成员函数。如果我们定义上面的函数为类的非成员函数,那么我们需要为每次操作传递两个参数,如下所示:

Box operator+(const Box&, const Box&);

下面的实例使用成员函数演示了运算符重载的概念。在这里,对象作为参数进行传递,对象的属性使用 this 运算符进行访问,如下所示:

#include <iostream>
using namespace std;
 
class Box
{
   public:
 
      double getVolume(void)
      {
         return length * breadth * height;
      }
      void setLength( double len )
      {
          length = len;
      }
 
      void setBreadth( double bre )
      {
          breadth = bre;
      }
 
      void setHeight( double hei )
      {
          height = hei;
      }
      // 重载 + 运算符,用于把两个 Box 对象相加
      Box operator+(const Box& b)
      {
         Box box;
         box.length = this->length + b.length;
         box.breadth = this->breadth + b.breadth;
         box.height = this->height + b.height;
         return box;
      }
   private:
      double length;      // 长度
      double breadth;     // 宽度
      double height;      // 高度
};
// 程序的主函数
int main( )
{
   Box Box1;                // 声明 Box1,类型为 Box
   Box Box2;                // 声明 Box2,类型为 Box
   Box Box3;                // 声明 Box3,类型为 Box
   double volume = 0.0;     // 把体积存储在该变量中
 
   // Box1 详述
   Box1.setLength(6.0); 
   Box1.setBreadth(7.0); 
   Box1.setHeight(5.0);
 
   // Box2 详述
   Box2.setLength(12.0); 
   Box2.setBreadth(13.0); 
   Box2.setHeight(10.0);
 
   // Box1 的体积
   volume = Box1.getVolume();
   cout << "Volume of Box1 : " << volume <<endl;
 
   // Box2 的体积
   volume = Box2.getVolume();
   cout << "Volume of Box2 : " << volume <<endl;
 
   // 把两个对象相加,得到 Box3
   Box3 = Box1 + Box2;
 
   // Box3 的体积
   volume = Box3.getVolume();
   cout << "Volume of Box3 : " << volume <<endl;
 
   return 0;
}

运行结果:

Volume of Box1 : 210
Volume of Box2 : 1560
Volume of Box3 : 5400
感谢战队让我进步飞快。尤其感谢战队里大佬们及身边同学们的不断支持与鼓励,感谢他们让我在极短的时间里了解到如此多的课堂上不会讲的知识,这是我受益匪浅,并且我乐意将知识不断分享给周边许多人!