C++_CH13_面向对象编程

C++_CH13_面向对象编程

1.1 类

类(class)是数据和操作的组合。
我们以游戏角色为例,创建一个类

#include<iostream>

class player//player这个类是我们自定义的一个类型
{
	int x;
	int y;//二维坐标
	int speed;//速度
	int power;//力量
	
};

int main()
{
	player KIMI; //创建了叫KIMI的角色,player是KIMI的数据类型
	KIMI.x = 10;
	KIMI.y = 9;//KIMI在二维平面的(10,9)这个点
	KIMI.power = 10000;//KIMI的力量有10000

}

KIMI叫player这个class的一个实例(instance)
对instance内部修改,用 instance.xxx的语法。

但是该段代码报错,是因为x,y这样的class内部的东西,没有被声明是全局的,他只在class player内部起作用。因此我们要加上public

#include<iostream>

class player//player这个类是我们自定义的一个类型
{
public:
	int x;
	int y;//二维坐标
	int speed;//速度
	int power;//力量
	
};

int main()
{
	player KIMI; //创建了叫KIMI的角色,player是KIMI的数据类型
	KIMI.x = 10;
	KIMI.y = 9;//KIMI在二维平面的(10,9)这个点
	KIMI.power = 10000;//KIMI的力量有10000

}

有了player,我们就可以写player的移动函数。

#include<iostream>

class player//player这个类是我们自定义的一个类型
{
public:
	int x;
	int y;//二维坐标
	int speed;//速度
	int power;//力量
	
};

void move(player& player,int xa,int ya)
{
	player.x += xa * player.speed; //移动距离乘以速度
	player.y += ya * player.speed;

}

int main()
{
	player KIMI; //创建了叫KIMI的角色,player是KIMI的数据类型
	move(KIMI,-1,+1)
}

我们也可以把move函数放到class里面,这样在class内的函数称为方法:

#include<iostream>

class player//player这个类是我们自定义的一个类型
{
public:
	int x;
	int y;//二维坐标
	int speed;//速度
	int power;//力量
	void move(player& player,int xa,int ya) 
	{
		player.x += xa * player.speed; //移动距离乘以速度
		player.y += ya * player.speed;

	}
};

int main()
{
	player KIMI; //创建了叫KIMI的角色,player是KIMI的数据类型
	move(KIMI,-1,+1)
}

此时已经在class内了,所以player都可以删掉

#include<iostream>

class player//player这个类是我们自定义的一个类型
{
public:
	int x;
	int y;//二维坐标
	int speed;//速度
	int power;//力量
	void move(int xa,int ya) 
	{
		x += xa * speed; //移动距离乘以速度
		y += ya * speed;

	}
};

int main()
{
	player KIMI; //创建了叫KIMI的角色,player是KIMI的数据类型
	player.move(-1,+1)
}

1.2类与结构体对比

区别在于类里面的数据和方法默认是private的,需要加public才能全局使用,而struct确是public的。如果想要使得一些是私有的,就在前面加private

#include<iostream>

struct player//player这个类是我们自定义的一个类型
{
	int x;
	int y;//二维坐标
	int speed;//速度
	int power;//力量
	void move(int xa,int ya) 
	{
		x += xa * speed; //移动距离乘以速度
		y += ya * speed;

	}
};

int main()
{
	player KIMI; //创建了叫KIMI的角色,player是KIMI的数据类型
	player.move(-1,+1)
}

struct能够被C++保留下来的唯一原因,就是因为想要向下兼容C。因为C是没有class的。
因此啥时候使用类,啥时候使用struct,完全取决于自己的代码风格。

1.3 一种代码风格

封装一些变量的时候用struct。struct只是关于数据的结构。当然struct里能写一些方法,但是推荐的这种风格一般都不会这样做。

对于一些有方法的结构,或者有继承的结构(继承之后会讲到),一般用类。

1.4 一种应用类的实例——log类管理日志

日志展示有三个level:

警告 warn 
追踪 trace
错误 error

我们写一个log类,来管理日志,在我们调用时只需要set一个我们希望展示的level级别就可以看到是什么级别的日志。如何实现呢?我们要以需求带动生产,所以我们现在main函数里写需求

#include<iostream>

class Log
{

};

int main()
{
	Log log; //创建一个Log类型的instance名字叫log‘
	log.SetLevel(LogLevelWarning);//使用log里的SetLevel方法,让我们输入希望展示的level层级
	log.warn("<WARNING>");//warn层级
	log.trace("INFO"); //追踪层级
	log.error("ERROR"); //错误层级

}

有了需求,我们要做的就是往 class Log里面填空。

#include<iostream>

class Log	
{
private://定义私有的一个变量,保存我们想要的log的level
	int m_LogLevel;

public:
	void Setlevel(int level)
	{
		m_Loglevel = level;//把外部我们给的level给m_LogLevel
	}
		
	void warn(const char* message)
	{
	}

	void trace(const char* message)
	{
	}

	void error(const char* message)
	{
	}
};

int main()
{
	Log log; //创建一个Log类型的instance名字叫log‘
	log.SetLevel(LogLevelWarning);//使用log里的SetLevel方法,让我们输入希望展示的level层级
	log.warn("<WARNING>");//warn层级
	log.trace("INFO"); //追踪层级
	log.error("ERROR"); //错误层级

}

写到这里我们可以看到level前面跟的是int,也就是说我们传的实参需要是int类型。那我们就可以这样规定:

warn: 0
trace: 1
error: 2

但是计算机不知道我们这样的规定。因此我们需要专门写一个变量,来储存这些规定。

#include<iostream>

class Log	
{
public:
	const int LogLevelWarn = 0;
	const int LogLevelTrace = 1;
	const int LogLevelError = 2;

private://定义私有的一个变量,保存我们想要的log的level
	int m_LogLevel = LogLevelError;//默认定义为2

public:
	void SetLevel(int level)
	{
		m_LogLevel = level;//把外部我们给的level给m_LogLevel,对本来的2进行了修改
	}
		
	void warn(const char* message)
	{
		if(m_LogLevel >= LogLevelWarn)
		{
			std::cout<<"<WARN>"<<std::endl;
		}
	}

	void trace(const char* message)
	{
		if(m_LogLevel >= LogLevelTrace)
		{
			std::cout<<"<TRACE>"<<message<<std::endl;
		}
	}

	void error(const char* message)
	{
		if(m_LogLevel >= LogLevelError)
		{
			std::cout<<"<ERROR>"<<message<<std::endl;
		}
	}
};

int main()
{
	Log log; //创建一个Log类型的instance名字叫log‘
	log.SetLevel(log.LogLevelError);//使用log里的SetLevel方法,让我们输入希望展示的level层级,修改这里的参数,填入我们想要的层级。
	log.warn("Hello");//warn层级
	log.trace("Hello"); //追踪层级
	log.error("Hello"); //错误层级

}

SetLevel(log.LogLevelWarn)
output:

<WARN>

SetLevel(log.LogLevelTrace)

<WARN>
<TRACE>Hello

SetLevel(log.LogLevelError)

<WARN>
<TRACE>Hello
ERRORHello

这样就成功得到了一个日志类。

当然这样的代码显然是非常不规范的。但是他非常有逻辑。之后会逐渐修改,知道达到工业界水平。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值