C++程序设计——面向对象程序设计(2)

提示:这是面向对象设计的第二部分,第一部分点这里

目录

前言

一、案例1:堆栈类

 1. stack.h头文件

 2. stack.cpp文件

二、面向对象编程进一步说明

1. 类的定义与实现

2. 数据成员与成员函数

3. 项目源程序之间的关系 

4. 访问控制 

5. 静态成员 

6. 预处理指令 

7. 构造函数

三、案例2:图书管理系统

1. 系统设计

2. 代码设计 

(1)Book类

(2)Reader类

(3)Manager类

(4) main 源文件

总结


前言

第一部分主要是面向对象设计的大致逻辑以及语法细节,然而本篇博客,同样来自于课堂内容,而课堂内容以实战为主,老师现场从零开始编写了图书馆借阅系统,受益良多。

本篇知识内容较少,侧重于实际项目,或者说样例。


一、案例1:堆栈类

设计一个整型堆栈(Stack)类,要求实现

  • 压入一个整数进栈:Push(e)
  • 弹出栈顶的整数:Pop()
  • 读栈顶的整数值:ReadTop()
  • 判断栈是否为空:IsEmpty()

编写main函数,测试堆栈类的正确性

  • 创建一个堆栈对象t1,依次压入整数13,-24,76
  • 输出t1栈顶的整数值,并输出栈是否为空
  • 依据t1创建另外一个栈t2
  • 从t2中连续4次弹出栈顶整数,并依次输出弹出的整数
  • 输出栈顶的整数值,并输出栈是否为空

 1. stack.h头文件

按照上述要求,可以设置头文件如下:

#ifndef __STACK_H
#define __STACK_H

class Stack
{
public:
	Stack(int size);
	Stack(const Stack& stack);
	~Stack();
	void Push(int e);
	int Pop();
	int ReadTop();
	bool IsEmpty();

private:
	int* m_data;
	int m_size;
	int m_top;
}; 

#endif

 2. stack.cpp文件

定义stack对象的成员函数

#include "stack.h"

#include <iostream>
using namespace std;

Stack::Stack(int size)
{
	m_data = new int[size];
	m_size = size;
	m_top = -1;
}

Stack::Stack(const Stack& stack)
{
	m_size = stack.m_size;
	m_top = stack.m_top;
	m_data = new int[m_size];
	for (int i = 0; i <= m_top; i++)
		m_data[i] = stack.m_data[i];
}

Stack::~Stack()
{
	delete[] m_data;
}

void Stack::Push(int e)
{
	if (m_top >= m_size - 1)
	{
		cout << "栈已满,无法压栈" << endl;
	}
	else
	{
		m_data[++m_top] = e;
	}
}

int Stack::Pop()
{
	if (m_top >= 0)
	{
		m_top--;
		return m_data[m_top + 1];
	}
	else
	{
		cout << "栈已空,无法弹栈" << endl;
		return -1;
	}
}

int Stack::ReadTop()
{
	if (m_top >= 0)
		return m_data[m_top];
	else
	{
		cout << "栈为空,无法读栈顶元素" << endl;
		return -1;
	}
}

bool Stack::IsEmpty()
{
	return m_top == -1;
}

二、面向对象编程进一步说明

1. 类的定义与实现

类的定义和实现一般放在不同的文件中

  • 类的定义一般放在一个头文件(Reader.h)中,供其它需要使用该类的文件包含
  • 类的实现一般放在一个源文件(Reader.cpp)中,该文件需要包含定义该类的头文件
  • 类的定义和实现可以放在一个文件里,但不提倡,因为结构不清晰

2. 数据成员与成员函数

  • 定义类时不能对数据成员进行初始化,数据成员的初始化放在构造函数
  • 类的成员函数的实现可以写在类里面,也可以写在外面
  • 为使程序结构更加清晰,除极短的函数外,建议成员函数的实现都放在源文件
     

3. 项目源程序之间的关系 

4. 访问控制 

 为实现信息隐藏和最低访问权原则:

  • 如果外部函数不需要访问某些数据,则不给它访问的权限
  • 如果外部函数只需要读某些数据,则只给它读的权限
  • 如果外部函数需要修改数据才给它全部的访问权限。即使如此,也应通过公有函数接口对私有数据进行修改
  • 如果只有少数外部函数和类需要修改数据,则将其设为友元函数和类

5. 静态成员 

 类的静态成员可以被该类的所有对象共享,包括静态数据成员和静态成员函数

  • 静态成员申明以关键字static开始,如: static int objNum;
  • 静态数据成员需要在定义类的时候就初始化,但不能在类里面初始化,只能在类外面初始化   int Reader::objNum = 0;
  • 静态成员的访问除了可以像普通成员通过对象访问之外,还可以通过类名加作用域运算符直接访问,如                                           Reader::objNum = 5;
  • 静态成员函数只能访问静态数据成员和静态成员函数,但非静态成员函数可以访问静态和非静态成员

6. 预处理指令 

 使用预处理指令防止头文件被源文件多次包含

#ifndef __BOOK_H    //预处理指令
#define __BOOK_H

class Book{
    ...
};

#endif

7. 构造函数

构造函数重载:重载构造函数以根据不同需要选择不同的对象初始化方法

默认构造函数:调用时不必提供参数的构造函数是默认构造函数,每个类只能有一个默认构造函数 

复制构造函数:根据类的某个对象复制出一个完全相同的新的对象的构造函数

  • 若不写复制构造函数,系统会自动生成一个复制构造函数,里面是对所有成员进行简单赋值
  • 若成员变量含有指针,且要动态分配内存,需要自己重写赋值构造函数,否则很容易出错
     

#ifndef __BOOK_H
#define __BOOK_H

class Book{
private:
    int m_id;	
    char m_name[100];
    bool m_state;

public:
    Book(); //默认构造函数
    Book(const Book& book); //复制构造函数
    Book(int id, char* name);
    //构造函数重载
};

#endif

//复制构造函数
#ifndef __STACK_H
#define __STACK_H

class Stack{
private:
    int* m_data;	

public:
    Stack();
    Stack(const Stack& stack);
};
#endif

三、案例2:图书管理系统

编写图书管理系统, 该系统可以

  • 添加图书、删除图书、打印所有的图书、打印未借出的图书、打印已借出的图书
  • 添加读者、删除读者、打印所有的读者信息
  • 借书、还书、显示借书列表

编写main函数,测试系统正确性

  • 添加4本图书、2个读者
  • 打印所有的图书和所有的读者
  • 删除第3本图书,然后打印所有未借出的图书
  • 读者1借剩下的第3本书,读者2借剩下的第1本书
  • 打印所有的图书信息

1. 系统设计

2. 代码设计 

(1)Book类

头文件

#ifndef __BOOK_H
#define __BOOK_H

class Reader;

class Book
{
private:
	long m_id;			// 图书ID
	char m_name[30];	// 图书名称
	bool m_state;		// 图书状态,false表示未借出,true表示已借出
	Reader* m_keeper;	// 借阅人

public:
	// 构造函数
	Book(long id, char name[]);

	// 析构函数
	~Book(){}

	// 打印书籍信息
	void ShowInfo();

	// 设置图书状态
	void SetState(bool state);

	// 获取图书状态
	bool GetState();

	// 设置借阅人
	void SetKeeper(Reader* r);

	// 获取书籍id
	long GetId();
};

#endif

源文件 

#include "book.h"
#include "reader.h"

#include <iostream>
using namespace std;

// 构造函数
Book::Book(long id, char name[])
{
	m_id = id;
	strcpy(m_name, name);
	m_state = false;
	m_keeper = NULL;
}

// 打印书籍信息
void Book::ShowInfo()
{
	cout << m_id << " " << m_name << " ";
	cout << (m_state ? "借出" : "未借出") << " ";
	if (m_keeper != NULL)
		cout << m_keeper->GetName();
	cout << endl;
}

// 设置图书状态
void Book::SetState(bool state)
{
	m_state = state;
}

// 获取图书状态
bool Book::GetState()
{
	return m_state;
}

// 设置借阅人
void Book::SetKeeper(Reader* r)
{
	m_keeper = r;
}

// 获取书籍id
long Book::GetId()
{
	return m_id;
}

(2)Reader类

头文件

#ifndef __READER_H
#define __READER_H

class Book;

class Reader
{
private:
	long m_id;				// 读者id
	char m_name[30];		// 读者姓名
	int m_brrBookNum;		// 借书数量
	Book* m_brrBooks[10];	// 借书列表

public:
	// 构造函数
	Reader(long id, char name[]);

	// 析构函数
	~Reader() {}

	// 打印读者信息
	void ShowInfo();

	// 获取读者姓名
	char* GetName();

	// 借书,若借书失败,返回false
	bool BorrowBook(Book* b);

	// 还书,若还书失败,返回false
	bool ReturnBook(Book* b);

	// 显示借阅书籍
	void ShowBrrBooks();

	// 获取读者id
	long GetId();

	// 是否有借书
	bool HasBrrBooks();
};

#endif

源文件 

#include "reader.h"
#include "book.h"

#include <string.h>
#include <iostream>
using namespace std;

// 构造函数
Reader::Reader(long id, char name[])
{
	m_id = id;
	strcpy(m_name, name);
	m_brrBookNum = 0;
	for (int i = 0; i < 10; i++)
		m_brrBooks[i] = NULL;
}

// 打印读者信息
void Reader::ShowInfo()
{
	cout << m_id << "\t" << m_name << "\t" << m_brrBookNum << endl;
}

// 获取读者姓名
char* Reader::GetName()
{
	return m_name;
}

// 借书,若借书失败,返回false
bool Reader::BorrowBook(Book* b)
{
	if (m_brrBookNum < 10)
	{
		m_brrBooks[m_brrBookNum++] = b;
		return true;
	}
	else
	{
		cout << "借书已满,借书失败" << endl;
		return false;
	}
}

// 还书,若还书失败,返回false
bool Reader::ReturnBook(Book* b)
{
	for (int i = 0; i < m_brrBookNum; i++)
	{
		if (m_brrBooks[i] == b)
		{
			m_brrBooks[i] = m_brrBooks[m_brrBookNum - 1];
			m_brrBooks[m_brrBookNum - 1] = NULL;
			m_brrBookNum--;
			return true;
		}
	}
	cout << "该图书不在当前读者的借阅书籍列表中,还书失败" << endl;
	return false;
}

// 显示借阅书籍
void Reader::ShowBrrBooks()
{
	for (int i = 0; i < m_brrBookNum; i++)
	{
		m_brrBooks[i]->ShowInfo();
	}
}

// 获取读者id
long Reader::GetId()
{
	return m_id;
}

// 是否有借书
bool Reader::HasBrrBooks()
{
	return m_brrBookNum > 0;
}

(3)Manager类

头文件

#ifndef __MANAGER_H
#define __MANAGER_H

#define MAX_READER_NUM 1000
#define MAX_BOOK_NUM 1000

class Reader;
class Book;

class Manager
{
private:
	Book* m_bookList[MAX_BOOK_NUM];			// 书籍列表
	int m_bookNum;							// 书籍数量
	Reader* m_readerList[MAX_READER_NUM];	// 读者列表
	int m_readerNum;						// 读者数量

public:
	// 构造函数
	Manager();

	// 析构函数
	~Manager();

	// 运行系统
	void Run();

	// 显示操作信息
	void ShowScreenInfo();

	// 添加图书
	void AddBook();

	// 删除图书
	void DeleteBook();

	// 打印所有图书
	void PrintAllBooks();

	// 添加读者
	void AddReader();

	// 删除读者
	void DeleteReader();

	// 打印所有读者
	void PrintAllReaders();

	// 借书
	void BorrowBook();

	// 还书
	void ReturnBook();
};

#endif

源文件 

#include "manager.h"
#include "book.h"
#include "reader.h"

#include <iostream>
using namespace std;

int book_id = 1000;
int reader_id = 2000;

// 构造函数
Manager::Manager()
{
	m_bookNum = 0;
	for (int i = 0; i < MAX_BOOK_NUM; i++)
		m_bookList[i] = NULL;

	m_readerNum = 0;
	for (i = 0; i < MAX_READER_NUM; i++)
		m_readerList[i] = NULL;
}

// 析构函数
Manager::~Manager()
{
	for (int i = 0; i < m_bookNum; i++)
		delete m_bookList[i];

	for (i = 0; i < m_readerNum; i++)
		delete m_readerList[i];
}

// 添加图书
void Manager::AddBook()
{
	cout << "请输入书籍名称:";
	char name[30];
	cin >> name;

	long id = ++book_id;

	Book* pbook = new Book(id, name);

	m_bookList[m_bookNum++] = pbook;
}

// 删除图书
void Manager::DeleteBook()
{
	cout << "请输入要删除的图书ID: ";
	int id;
	cin >> id;

	for (int i = 0; i < m_bookNum; i++)
	{
		if (m_bookList[i]->GetId() == id)
		{
			if (m_bookList[i]->GetState() == true)
			{
				cout << "书籍已借出,请还书后再删除" << endl;
			}
			else
			{
				delete m_bookList[i];
				for (int j = i; j < m_bookNum - 1; j++)
					m_bookList[j] = m_bookList[j + 1];
				m_bookNum--;
			}
			break;
		}
	}
}

// 打印所有图书
void Manager::PrintAllBooks()
{
	for (int i = 0; i < m_bookNum; i++)
	{
		m_bookList[i]->ShowInfo();
	}
}

// 添加读者
void Manager::AddReader()
{
	cout << "请输入读者姓名:";
	char name[30];
	cin >> name;

	long id = ++reader_id;

	Reader* preader = new Reader(id, name);

	m_readerList[m_readerNum++] = preader;
}

// 删除读者
void Manager::DeleteReader()
{
	cout << "请输入要删除的读者ID: ";
	int id;
	cin >> id;

	for (int i = 0; i < m_readerNum; i++)
	{
		if (m_readerList[i]->GetId() == id)
		{
			if (m_readerList[i]->HasBrrBooks())
			{
				cout << "该读者有借书,请还书后再删除" << endl;
			}
			else
			{
				delete m_readerList[i];
				for (int j = i; j < m_readerNum - 1; j++)
					m_readerList[j] = m_readerList[j + 1];
				m_readerNum--;
			}
			break;
		}
	}
}

// 打印所有读者
void Manager::PrintAllReaders()
{
	for (int i = 0; i < m_readerNum; i++)
	{
		m_readerList[i]->ShowInfo();
	}
}

// 借书
void Manager::BorrowBook()
{
	cout << "请输入借阅人id: ";
	int rId;
	cin >> rId;

	cout << "请输入书籍id: ";
	int bId;
	cin >> bId;

	Book* b = NULL;
	for (int i = 0; i < m_bookNum; i++)
	{
		if (m_bookList[i]->GetId() == bId)
			b = m_bookList[i];
	}

	Reader* r = NULL;
	for (i = 0; i < m_readerNum; i++)
	{
		if (m_readerList[i]->GetId() == rId)
			r = m_readerList[i];
	}

	if(r->BorrowBook(b) == true)
	{
		b->SetState(true);
		b->SetKeeper(r);
	}	
}

// 还书
void Manager::ReturnBook()
{
}

// 显示操作信息
void Manager::ShowScreenInfo()
{
	cout << "=================" << endl;
	cout << "1: 添加图书" << endl;
	cout << "2: 删除图书" << endl;
	cout << "3: 打印图书" << endl;
	cout << "4: 添加读者" << endl;
	cout << "5: 删除读者" << endl;
	cout << "6: 打印读者" << endl;
	cout << "7: 借书" << endl;
	cout << "8: 还书" << endl;
	cout << "=================" << endl;
}

// 运行系统
void Manager::Run()
{
	while(1)
	{
		system("cls");

		ShowScreenInfo();

		cout << "请选择对应的操作:";
		int op;
		cin >> op;

		switch(op)
		{
		case 1:
			AddBook();
			break;
		case 2:
			DeleteBook();
			break;
		case 3:
			PrintAllBooks();
			break;
		case 4:
			AddReader();
			break;
		case 5:
			DeleteReader();
			break;
		case 6:
			PrintAllReaders();
			break;
		case 7:
			BorrowBook();
			break;
		case 8:
			ReturnBook();
			break;
		default:
			break;			
		}

		cout << "请按任意键继续操作" << endl;
		char c;
		cin >> c;
	}
}

(4) main 源文件

#include "manager.h"

int main()
{
	Manager mgr;

	mgr.Run();

	return 0;
}


总结

还是要动手实操,自己尝试面向对象编写项目,才能更好的掌握面向对象编程的能力。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值