类、结构体、指针、引用

来自博主本人的碎碎念:
差点变成“月更”的这位“日更”博主终于更新啦hhhhhh
这篇应该是关于C++语法的最后一篇!
对于这个账号,我是打算把它当成一个记录学习的地方,所以在今后,这里除了会更新算法题解,还可能会有六级英语学习笔记、html等等哦(说不定我明天就更新科三的学习心得了hhh)
感谢各位粉丝的关注!(开学了不能做到日更了,但我尽量两三天就更新一下)
谢谢大家!!!记得点赞哦!!!嘻嘻

类、结构体、指针、引用

一、类与结构体:

类可以将变量、数组和函数完美地打包在一起——y总

类的定义:

类的里面有两个关键字:private 和 public

private:表示它后面所有的函数、变量等内容都是私有的,是私有成员变量,只能在类的里面调用,在类的外面不能调用(就相当于private是私人的东西,你不能用别人的)

public:表示它后面所有的内容是共有成员变量,在类的外面可以调用,也可以在类的里面调用(public是公共的东西,就相当于在学校里的黑板擦,大家都可以用)

#include <iostream>

using namespace std;

//类——class 
class Person//相当于定义了一个新的类型,叫做Person,里面存放了人的所有信息 
{
	private:
		int age,height;//定义人的年龄和身高(只能在类里面用) 
		double money;//定义同学的零花钱 
		string books[100];//表示同学的书的名字 
		
		int get_height()//private里也可以定义函数,例如下 
		{
			return height;
		} 
		
	public:
	    string name;//定义同学的姓名 
		
		void say()
		{
			cout<<"I'm "<<name<<endl;//”我是谁“ 
		}	
		
		int get_age()//得到年龄,因为age是在这个类里的,所以函数可以调用 
		{
			return age;
		}
		
		void add_money(double x)//妈妈给小孩发零花钱啦! 
		{
			money+=x;
		}
};//类的后面一定要加上";" 

在类里面,private和public可以有多个,例如:

#include <iostream>

using namespace std;

//类——class 
class Person//相当于定义了一个新的类型,叫做Person,里面存放了人的所有信息 
{
	private:
		int age,height;//定义人的年龄和身高(只能在类里面用) 
		double money;//定义同学的零花钱 
		
		int get_height()//private里也可以定义函数,例如下 
		{
			return height;
		} 
		
	public:
	    string name;//定义同学的姓名 
		
		void say()
		{
			cout<<"I'm "<<name<<endl;//”我是谁“ 
		}	
		
		int get_age()//得到年龄,因为age是在这个类里的,所以函数可以调用 
		{
			return age;
		}
		
		void add_money(double x)//妈妈给小孩发零花钱啦! 
		{
			money+=x;
		}
		
	private://多个private在这里hhh
		string books[100];//表示同学的书的名字 
}c,persons[100];//类的后面一定要加上";"
//可以在后面直接定义一个变量c,也可以在后面定义一个数组

注:每个private和public修饰的所有变量指的是它冒号后面,下一个关键词之前的所有变量

类中的变量和函数被统一称为类的成员变量

类的使用:

#include <iostream>

using namespace std;

//类——class 
class Person//相当于定义了一个新的类型,叫做Person,里面存放了人的所有信息 
{
	private:
		int age,height;//定义人的年龄和身高(只能在类里面用) 
		double money;//定义同学的零花钱 
		
		int get_height()//private里也可以定义函数,例如下 
		{
			return height;
		} 
		
	public:
	    string name;//定义同学的姓名 
		
		void say()
		{
			cout<<"I'm "<<name<<endl;//”我是谁“ 
		}	
		
		int get_age()//得到年龄,因为age是在这个类里的,所以函数可以调用 
		{
			return age;
		}
		
		void add_money(double x)//妈妈给小孩发零花钱啦! 
		{
			money+=x;
		}
		
	private:
		string books[100];//表示同学的书的名字 
};//类的后面一定要加上";" 

int main()
{
	Person c;//把上面定义的名字拿过来,当成是一个新的类型,然后定义一个同学c
	Person persons[1000];//也可以这样定义一个数组
    
	c.name="qf";//把c同学的名字取名为qf,因为name是一个共有变量,所以可以在外部(这里)访问
	//c.age=3;
	//c同学3岁!!!这是一个错误的定义!!!因为age是一个私有变量,在外部访问会错误(qf的年龄怎么能告诉别人呢hhh) 
	cout<<c.get_age()<<endl;//因为age没有赋过值,所以输出的是一个随机的值 
	c.add_money(1000000);//qf的妈妈给了qf这么多零花钱(我在做梦),add_money是一个共有函数,可以外部调用 
	 
	return 0;
}

结构体和类的作用一样,不同之处在于:

如果在类里的变量前不加private或者public,默认是private私有变量

如果在结构体里变量前不加private或者public,默认是public共有变量

(在习惯上,一般把数据比较少的定义成结构体,把代码比较长的打包成class)

struct Person
{
	private:
		int age,height;
		double money;
		string books[100];
		
	public:
		string name;
		
		void say()
		{
			cout<<"I'm "<<name<<endl;
		}
		
		int set_age(int a)
		{
			age=a;
		}
		
		int get_age()
		{
			return age;
		}
		
		void add_money(double x)
		{
			money+=x;
		}
}person_a,person_b,persons[100];
类和结构体里有构造函数:
#include<iostream>

using namespace std;

struct Person
{
		int age,height;
		double money;
		
		//可以定义一个构造函数 ,构造函数是没有类型的,名字一定是和结构体的名字是完全一样的,构造函数里面是可以写参数的 
	
	    Person(int _age,int _height,double _money)//构造函数 
	    {
	    	age=_age;//可以在函数内部将Person的几个变量进行赋值
	    	height=_height;
	    	money=_money;
	    }
};

int main()
{
	Person p(3,175,100.0);//因为上面构造了函数,所以它可以直接调用函数
	//Person p;错误!!!因为这个结构体里就定义了一个函数,必须要提供三个参数才行 
	 
	return 0;
}
#include<iostream>

using namespace std;

struct Person
{
		int age,height;
		double money;
    
	    Person() {}//定义一个没有参数的空的构造函数 
	    
	    Person(int _age,int _height,double _money)//构造函数 
	    {
	    	age=_age;//可以在函数内部将Person的几个变量进行赋值
	    	height=_height;
	    	money=_money;
	    }
};

int main()
{
	Person p; //上面定义了空的构造函数,这里就不会报错了 
	//当我们直接定义变量而没有给初值的时候,它会调用默认构造函数
	return 0;
}
结构体的初始化的另外几种方式:
#include<iostream>

using namespace std;

struct Person
{
		int age,height;
		double money;
	
	    Person() {}//定义一个没有参数的空的构造函数 
	    
        Person(int _age,int _height){}//手动定义两个参数的构造函数,防止报错
    
	    Person(int _age,int _height,double _money)//构造函数 
	    {
	    	age=_age;//可以在函数内部将Person的几个变量进行赋值
	    	height=_height;
	    	money=_money;
	    }
};

int main()
{
	Person p={3,180,100}; //会按照上面定义的方式顺次赋值
    Person p={3,180};
    //因为上面只定义了没有参数的构造函数和有三个参数的构造函数,所以如果只赋值两个值会报错
	return 0;
}
还有一种赋值方式,可以使代码的运行速度更快一点:
#include<iostream>

using namespace std;

struct Person
{
		int age,height;
		double money;
	
	    Person(int _age,int _height):age(_age),height(_height) {}
	    
	    Person(int _age,int _height,double _money):age(_age),height(_height),money(_money){}
};

int main()
{
	Person p={3,180,100}; //上面定义了空的构造函数,这里就不会报错了 
	 
	return 0;
}

注:class里也有构造函数,和struct完全一样,就是写的时候注意加上public:

二、指针和引用

指针指向存放变量的值

所有程序都是一个进程,不同进程之间相互独立,而且进程有一个空间的概念(一般所说的空间是指内存,内存有8GB、16GB等)比如说自己的电脑有4GB,那么在自己看来就是电脑有个从0到4GB的数组,而地址在编码的时候是用16进制编码的,意味着地址是从0×00000000到0×FFFFFFFF.现在的电脑一般是64位的,就是意味着地址是64位的,就是地址是从0×0000000000000000到0×FFFFFFFFFFFFFFFF,关于内存空间,如图(堆栈空间)

在这里插入图片描述

所有的函数调用都是在栈空间里面进行操作的,局部变量都是定义到栈空间里面的,静态变量和数组是全部定义到堆空间里面的,因为开到栈里面的变量是没有赋值的,所以值是不确定的,而开到堆里面的变量会全部默认初始化为0。

比如里面开了一个char类型变量,存了一个字符a…难以形容

#include<iostream>
#include<cstdio>

using namespace std;

int main()
{
	char c='a';
	cout<<(void*)&c<<endl;//转化成指针的形式输出c的地址 
	 
	return 0;
}

如果连续定义的话,地址也是连续的

在这里插入图片描述

里面定义的地址:

在这里插入图片描述

综上:堆空间分配是从小到大的地址分配,栈空间分配是从大到小的地址分配

关于指针的一些用法:

指针就是存放内存的数组下标,它指向存放变量的值的地址。因此我们可以通过指针来修改变量的值

#include<iostream>
#include<cstdio>

using namespace std;

char a,b;

int main()
{
	int a=10;//在栈空间里定义一个变量a 
	int* p=&a;//p是a的地址 ,这里的"*"指的是定义的变量是指针类型,*和p没关系,把int*放一起看,是int类型的指针,p是变量的名字 
	
	cout<<*p<<endl;//这里的"*"表示一个操作符,意思是取这个p的地址 
	
	return 0;
}
#include<iostream>
#include<cstdio>

using namespace std;

char a,b;

int main()
{
	int a=10;//在栈空间里定义一个变量a 
	int* p=&a;//p是a的地址 ,这里的"*"指的是定义的变量是指针类型,*和p没关系,把int*放一起看,是int类型的指针,p是变量的名字 
	
    //p虽然存的是地址,但p本身也有变量,因为存放p的地方其实也有地址
    //int** q=&p;
    //cout<<q<<endl;还可以继续套娃hhh
    
	cout<<*p<<endl;//这里的"*"表示一个操作符,意思是取这个p的地址 
	*p=12;//给p赋值 
	
	cout<<*p<<endl;
	cout<<a<<endl;//a的值也发生了相应变化
	 
	return 0;
}

运行结果证明:

在这里插入图片描述

数组名是一种特殊的指针。指针可以做运算

代码:

#include<iostream>
#include<cstdio>

using namespace std;

char a,b;

int main()
{
	int a[5]={1,2,3,4,5};
	
	cout<<a<<endl;
	 
	return 0;
}

运行结果证明:

在这里插入图片描述

代码:

#include<iostream>
#include<cstdio>

using namespace std;

char a,b;

int main()
{
	char c;
	int a[5]={1,2,3,4,5};
	
	int *p=a;
	cout<<*p<<endl;//输出的是a[0] 
	
	return 0;
}

运行证明结果如下:

在这里插入图片描述

代码:

#include<iostream>
#include<cstdio>

using namespace std;

int main()
{
	int a[5]={1,2,3,4,5};
	
	for(int i=0;i<5;i++)
	{
		cout<<*(a+i)<<endl;//举例,a[1]等于a+1
	}

	return 0;
}

运行结果证明:

在这里插入图片描述

引用和指针类似,相当于给变量起了个别名
#include<iostream>
#include<cstdio>

using namespace std;

char a,b;

int main()
{
	int a=10;
	int* p=&a;//c语言的写法,定义了一个指针p,它是a的地址 
	int& p=a;//c++写法,引用、别名,定义了一个变量p,p和a存到了一个地址上面 
	
	
	return 0;
}

三、链表

链表定义:定义一个结构体,里面存两个值,一个是val,一个是next指针

在这里插入图片描述

#include <iostream>

using namespace std;

struct Node
{
	int val;
	Node* next;//定义结构体的时候,可以在结构体内部定义一个它的指针,但不能定义变量如Node next会报错(因为这里是递归定义) 
	
	Node(int _val):val(_val),next(NULL){}
};

int main()
{
   Node* p=new Node(1);
   Node* q=new Node(2);
   Node* o=new Node(3);
   
   p->next=q;//p存的地址是1号结点地址,q存的是2号结点地址,o存的是3号结点地址 
   q->next=o;//1号指向2号,2号指向3号,3号指向空
   
   //这种结构称为单链表
   //一般把第一个结点的地址称为头结点,要把头结点的地址存下来,存在head里面 
   
   Node* head=p;
    
   //在链表中添加结点
   Node* u=new Node(4);
   u->next=head;
   head=u;
   
   //删除结点(是指在遍历时遍不到这个点了)
   head->next=head->next->next;
   
   //链表的遍历方式 
   for(Node* i=head;i!=0;i=i->next)
   {
   	cout<<i->val<<endl;
   } 
   
   return 0;
	 
}
  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值