学习笔记C++_2 类基础

一. 类封装

https://www.runoob.com/cplusplus/cpp-classes-objects.html
C++ 类 & 对象 | 菜鸟教程 (runoob.com)

问题:数据和算法彼此独立,关联性不强

class:定义类的关键字,类名一般以C开头

访问修饰符:描述了类中成员所能使用的一个范围,即权限限制,默认是private(私有的)
    public:类成员在任何地方都可以使用
    protected:在类中和子类中可以使用
    private:只能在类中使用

成员属性/变量:类对象的属性也称为成员变量

成员方法:使用成员方法对应于类对象的行为

当方法的局部变量和类的成员变量重名时,就近原则优先使用局部变量,成员变量被屏蔽。此时若要使用成员变量,就需要用 “this->成员变量名” 的格式来引用成员变量

#include <iostream>

using namespace std;

class CPeople {	//抽象
public:
	string name;	//名字
private:
	int m_nAge;	//年龄
protected:
	bool m_bSex;	//性别

public:
	void eat() {
		cout << name << " eating" << endl;
	}
	void show() {
		cout << name << " " << m_nAge << " " << m_bSex << endl;
	}
	//公共的接口函数
	void Init(string name) {
		this->name = name;
		m_nAge = 21;
		m_bSex = 1;
	}
};


int main() {
	//具体
	CPeople peo;	//类 类名的变量,称之为 对象
	peo.name = "张三";
	peo.eat();
	peo.Init("李四");
	peo.show();
}

class命名习惯:

类名 "C"开头

成员变量 "m_"+数据类型"n"(int)+变量名 

1.1 构造函数 

若采取上述的初始化方式,每一次定义类都要调用一遍,有没有一种可以在定义时自动初始化的方式呢?

构造函数:函数名为当前的类名,没有返回类型(不是void)

参数:如果没有手动重构 构造函数,编译器会默认添加构造函数,默认无参构造
          如果是手动重构的话,编译器就不会提供,默认无参构造,可以根据实际情况 自行添加参数

CPeople() {
		m_strName = "阿里巴巴";
		m_nAge = 20;
		m_bSex = 0;
	}
	//一个类中构造函数可以存在多个。它们之间的关系是重载
	CPeople(string name, int age, bool sex) {
		m_strName = name;
		m_nAge = age;
		m_bSex = sex;
	}

作用:用来给类中的成员属性做初始化。定义对象时,编译器自动调用构造函数

默认无参构造函数体代码->为空 CPeople() {},多数情况下,需要手动重构构造函数

一个类中可以有多个构造函数,但对象创建时只会执行其中一个

1.2 析构函数

函数名:~Cpeople ,没有返回类型,无参数

编译器默认提供的默认析构函数,则函数体代码为空

作用:用来回收类中成员 额外申请的 空间

调用时间:对象的生命周期结束时,编译器会自动调用析构函数(编译器先调用析构函数回收额外申请的空间,再由编译器回收对象本身的空间)

char* m_pNote = new char[] {"abcd"};
~CPeople() {
	if (m_pNote)
		delete[] m_pNote;
	m_pNote = nullptr;
}

析构函数一个类中永远只会存在一个

空类默认产生的成员函数

构造函数、拷贝构造函数、析构函数、赋值运算符、取址运算符、取址运算符 const

class Empty{
public:
    Empty();// 缺省构造函数

    Empty(const Empty&);// 拷贝构造函数

    ~Empty();// 析构函数

    Empty& operator=(const Empty& ); // 赋值运算符

    Empty* operator&();// 取址运算符

    const Empty* operator&() const;// 取址运算符 const
};

二. 链表封装(类)

#include <iostream>

using namespace std;
/*
在C++ 中 结构体  和  类的区别:
1. 结构体 默认的访问修饰符 为 public, 类的默认访问修饰符  private
2. 结构体 默认继承方式 为 public,类 默认继承方式 为 private,
*/
typedef struct node {
	int data;
	node* next;
	node(int data) {
		this->data = data;
		next = nullptr;
	}
}Node,*PNode;

class CLinkedList {
private:
	PNode header;
	PNode ender;
	int len;
public:
	CLinkedList() {
		header = ender = nullptr;
		len = 0;
	}
	~CLinkedList() {
		PNode temp;
		while (header) {
			temp = header;
			header = header->next;
			delete temp;	//释放指针指向的内存
			temp = nullptr;		//指针赋空,避免非法性判断
			len--;
		}
	}
	void PushBack(int data) {
		PNode p = new Node(data);	//堆区
		if (len == 0)
			header = ender = p;	//指针指向节点所申请的空间
		else {
			ender->next = p;
			ender = p;
		}
		len++;
	}
	void PopFront() {
		if (header) {
			PNode temp = header;
			if (header == ender) {
				header = ender = nullptr;
			}
			else {
				header = header->next;
			}
			delete temp;
			temp = nullptr;
			len--;
		}
	}
	void showList() {
		PNode p = header;
		while (p) {
			cout << p->data << ' ';
			p = p->next;
		}
		cout << endl;
	}
	int getLen() {
		return len;
	}
};

int main() {
	Node p(1);
	CLinkedList list;
	list.PushBack(10);
	list.PushBack(20);
	list.PushBack(30);
	list.PushBack(40);
	list.PushBack(50);
	list.showList();
	cout << list.getLen() << endl;
	list.PopFront();
	list.showList();
	cout << list.getLen() << endl;
}

三. 人物移动

#include <iostream>
#include <easyx.h>
#include <conio.h>	//控制台输入

using namespace std;

#define KEY_UP       72
#define KEY_DOWN     80
#define KEY_LEFT     75
#define KEY_RIGHT    77
#define ESC 27

#define MOVE_STEP 10

const int screenWidth = 600;
const int screenHeight = 600;

class CPeople {
private:
	//人物显示的坐标
	int m_x, m_y;

	//图片绑定
	IMAGE m_up, m_down, m_left, m_right;

	int m_direct;

public:
	CPeople() {
		//::将函数限制在当前作用域,防止class中有重名方法
		::initgraph(screenWidth, screenHeight);	//创建窗口
		::setbkcolor(RGB(233, 101, 123));	//设定背景颜色
		::cleardevice();	//使背景颜色立即生效,不然只有到窗口有绘制操作时才会更新

		m_x = screenWidth / 2;
		m_y = screenHeight / 2;

		//图片变量 和 具体的图片资源绑定
		::loadimage(&m_up, L".\\res\\up.bmp");
		::loadimage(&m_down, L".\\res\\down.bmp");
		::loadimage(&m_left, L".\\res\\left.bmp");
		::loadimage(&m_right, L".\\res\\right.bmp");

		m_direct = KEY_RIGHT;	//初始方向为右
	}
	~CPeople() {
		::closegraph();	//关闭窗口
	}
	void showPeople() {
		::cleardevice();
		//开始批量重绘
		::BeginBatchDraw();

		if(m_direct==KEY_UP)
			::putimage(m_x, m_y, &m_up);
		if (m_direct == KEY_DOWN)
			::putimage(m_x, m_y, &m_down);
		if (m_direct == KEY_LEFT)
			::putimage(m_x, m_y, &m_left);
		if (m_direct == KEY_RIGHT)
			::putimage(m_x, m_y, &m_right);
		//结束批量重绘
		::EndBatchDraw();
	}
	void MovePeople(int direct) {	//键盘传递方向
		switch (direct) {
		case KEY_UP:
			if (m_y - MOVE_STEP >= 0)
				m_y -= MOVE_STEP;
			else m_y = 0;
			break;
		case KEY_DOWN:
			if (m_y + MOVE_STEP <= screenHeight - 60)
				m_y += MOVE_STEP;
			else m_y = screenHeight - 60;
			break;
		case KEY_LEFT:
			if (m_x - MOVE_STEP >= 0)
				m_x -= MOVE_STEP;
			else m_x = 0;
			break;
		case KEY_RIGHT:
			if (m_x + MOVE_STEP <= screenWidth - 60)
				m_x += MOVE_STEP;
			else m_x = screenWidth - 60;
			break;
		default:
			direct = m_direct;
		}
		m_direct = direct;	//更新方向
	}
	void RunGame() {
		showPeople();
		while (1) {
			//不打断获取方向键
			int key = _getch();	//获取键盘按键的字符码
			if (key == ESC) {
				int ret = ::MessageBox(NULL, L"确定退出嘛?", L"提示", MB_YESNO);	//弹出弹出框
				if (ret == IDYES) {
					break;
				}
				else {	//IDNO
					continue;
				}
			}
			//如果获取到了,调用移动的方法,传参
			MovePeople(key);
			//刷新窗口 显示人物
			showPeople();
		}
	}
};



int main() {
	CPeople p;
	p.RunGame();
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值