0
点赞
收藏
分享

微信扫一扫

C++多态--显示控件函数;控件监听函数;按键响应函数

萧萧雨潇潇 2022-04-23 阅读 61
c++

一:纯虚函数和虚函数 重写和重定义

每一个派生类的实现方式都不一样,基类不知道应该如何实现--纯 虚函数

带有纯 虚函数的类--->抽象类

派生类实现基类的纯 虚函数--重写(纯 虚函数--重写)基类没有任何实现方法

派生类重定义基类函数--虚函数 (虚函数--重定义)  基类有方法,若子类有方法走子类方法

二:显示控件函数 控件监听函数 按键响应函数(多态--C++精髓)

    virtual void show()=0;         //显示控件函数 纯虚函数-重写
    virtual void keyListen(char ch);//控件监听函数 虚函数-重定义 
	//在基类声明时加虚  定义时候不加
	virtual int doAction()=0; //窗口切换  纯虚函数的类-抽象类
//虚函数 可以让每一个函数的子类都能去调用
void CtrBase::keyListen(char ch)  //虚函数里面可以没有任何内容 全部子类各自实现各自方法
{
}

三:界面切换

1.main.cpp

#include<iostream>
using namespace std;
#include "CLabel.h"
#include"CEdit.h"
#include"CButton.h"
#include"CTools.h"
#include"CLogin.h"
#include"CtrBase.h"
#include"CIndexWin.h"//管理员主界面窗口
#include<cstdlib>

int main()
{
	CLoginWin *login = new CLoginWin(12,5,30,20);
    CIndexWin *index = new CIndexWin(3,3,25,23);

	CWinBase *winArr[10] = {0};

	winArr[0] = login;  //点菜界面
	winArr[1] = index;  //管理员界面

	int winIndex = 0;  //默认显示点菜界面 初始化为0
	
	while(1)
	{
		system("cls");
		winArr[winIndex]->showWindow();
		winIndex = winArr[winIndex]->WinRun();
	}
	return 0;
}

2.CTools.h

#ifndef CTOOLS_H
#define CTOOLS_H
#define KEY_UP 72
#define KEY_DOWN 80
#define KEY_LEFT 75
#define KEY_RIGHT 77
#define KEY_ESC 27
#define KEY_ENTER 13
 
class CTools  //工具类
{
public:
//所有的方法都是静态方法
static void paintWindow(int startX,int startY,int width,int height);//打印窗口
 
static void gotoxy(int x,int y);//形参  光标定位
 
/*
函数功能:字符串输入控制
函数参数:
int maxLen    允许输入最大长度
int inputType 允许输入的字符类型  0:数字 1:字母 2:字母+数字
int ips       数据显示格式        0:密文 1:明文
char str[] 存储输入字符
函数返回值:无
char str[]    char str[20]    char*str
*/
static void glb_string(int maxLen,int inputType,int ips,char str[]); 
 
/*
函数名:int getkey()
函数功能:获取用户输入的任意键盘值
函数参数:无
函数返回:ascii  
*/
static int getkey();
};
 
#endif

3.CTools.cpp

#include "CTools.h"
#include <windows.h>   //引用库头文件
#include<stdio.h>
#include<conio.h>
 
void CTools::gotoxy(int x,int y)//形参
{
	HANDLE hOut;
	COORD pos= {x,y};
	// 光标的起始位(第1列,第3行) 0是第1列 2是第3行
	hOut = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleCursorPosition(hOut, pos);
	//printf("定位光标位置搜索(%d,%d)\n",pos.X,pos.Y);
}
 
void CTools::paintWindow(int startX,int startY,int width,int height) 
{
	int i=0;
	//打印顶部   
	//光标定位 找规律 ┗  ┛ ┏ ┓ ┃ ━
	//顶部 y不变 x 在变 (x-x+w)
	gotoxy(startX,startY);
	printf("┏");
	for(i=0;i<width-2;i++)  //控制循环次数width-2次
	{
		printf("━ ");
	}
	printf("┓");
 
	//左边 x不变 y在变 (y到y+height)	
	for(i=1;i<=height-1;i++)
	{
		gotoxy(startX,startY+i);
		printf("┃");
	}
	
	//右边 x不变 =startx+width-1  y在变 y 到 y+height
	for(i=1;i<=height-1;i++)
	{
		gotoxy(startX+width*2-3,startY+i);
		printf("┃");
	}
 
	//底部 x在变化    y不变 (x到x+width) ━ 
	gotoxy(startX,startY+height-1);
	printf("┗");
	for(i=0;i<width-2;i++)
	{
		printf("━ ");	
	}
	printf("┛");
 
	gotoxy(startX,startX+height);
}
 
void CTools::glb_string(int maxLen,int inputType,int ips,char str[])
{
	   char ch=0;
	   int i=0;
	   while(1)
	   {
		   ch=getch();
		   if(ch=='\r'&&i>0)//换行结束输入
		   {	   
			   break;	   
		   }
		   switch(inputType)
		   {
		   case 0:
			   if(ch>='0'&&ch<='9'&&i<maxLen)
			   {
				   if(ips==0)
				   {
					   putch('*');	   
				   }
				   else{			   
					   putch(ch);
				   }
				   str[i++]=ch;		   
			   }
			   break;
		   case 1:
			   if(i<maxLen&&(ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))
			   {
				   if(ips==0)
				   {
					   putch('*');   
				   }
				   else{   
					   putch(ch);
				   }
				   str[i++]=ch;   
			   }
			   break;
		   case 2:
			   if(i<maxLen&&(ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch>='0'&&ch<='9'))
			   {
				   if(ips==0)
				   {
					   putch('*');
				   }
				   else{  
					   putch(ch);
				   }
				   str[i++]=ch;   
			   }
			   break;
		   default:
			   break; 
		   }
	   }	    
}
 
/*
函数名:int getkey()
函数功能:获取用户输入的任意键盘值
函数参数:无
函数返回:ascii  
*/
int CTools::getkey()
{
	char key=0;
	key=getch();
	if(key==-32)//方向按键 第一个值都是32
	{
		key=getch();
		switch(key){
		case 72:
			return KEY_UP;
		case 80:
			return KEY_DOWN;
		case 75:
			return KEY_LEFT;
		case 77:
			return KEY_RIGHT;
		}	
	}
	else if(key==13)
	{
		return KEY_ENTER;
	}
	else if(key==27)
	{
		return KEY_ESC;
	}
	return key;
}

4.CtrBase.h

#ifndef CTRBASE_H
#define CTRBASE_H
#define LABEL 1
#define EDIT 2
#define BUTTON 3

class CtrBase
{
public:
	CtrBase();
	~CtrBase();
	CtrBase(int x,int y,int w,int h,char *pcontent,int ctrlType);
    virtual void show()=0;         //显示控件函数 纯虚函数-重写
//类外访问使用get方法
	int getX();
	int getY();
	int getW();
	int getH();
	char *getContent();
	int getType();  //返回控件类型
    virtual void keyListen(char ch);//控件监听函数 虚函数-重定义 
protected:   
	int startX;
	int startY;
	int width;
	int height;
	char content[20];  //内容
	int ctrlType;      //控件类型
};

#endif

5.CtrBase.cpp

#include"CtrBase.h"
#include"CTools.h"
#include<iostream>
using namespace std;

CtrBase::CtrBase()
{
	this->startX = 0;
	this->startY = 0;
	this->width = 0;
	this->height = 0;
	memset(this->content,'\0',sizeof(this->content));
	this->ctrlType = 0;
}

CtrBase::~CtrBase()
{
}

CtrBase::CtrBase(int x,int y,int w,int h,char *pcontent,int type)
{
	this->startX = x;
	this->startY = y;
	this->width = w;
	this->height = h;
	//内存的初始化
	memset(this->content,'\0',sizeof(this->content));
	strcpy(this->content,pcontent);
	this->ctrlType = type;
}

/*   注释(基类什么都不写) 代表纯虚函数
void CtrBase::show()//基类 有写内容  是虚函数
{
	CTools::gotoxy(this->startX,this->startY);
    cout<<this->content<<endl;
}
*/

//类外访问
//为类对象访问提供公共接口
int CtrBase::getX()
{
	return this->startX;
}
int CtrBase::getY()
{
    return this->startY;
}
int CtrBase::getW()
{
    return this->width;
}
int CtrBase::getH()
{
    return this->height;
}
char* CtrBase::getContent()
{
	return this->content;
}
int CtrBase::getType()
{
	return this->ctrlType;
}

//虚函数 可以让每一个函数的子类都能去调用
void CtrBase::keyListen(char ch)  //虚函数里面可以没有任何内容 全部子类各自实现各自方法
{
}

6.CLabel.h

#ifndef CLABEL_H
#define CLABEL_H
#include"CtrBase.h"

class CLabel:public CtrBase   
{
public:
	CLabel();
	~CLabel();
	CLabel(int x,int y,int w,int h,char pcontent[20],int type);
	void show();  
private:   
};

#endif

7.CLabel.cpp

#include"CLabel.h"
#include<iostream>
using namespace std;
#include"CTools.h"

CLabel::CLabel()
{
}

CLabel::CLabel(int x,int y,int w,int h,char pcontent[20],int type)
:CtrBase(x,y,w,h,pcontent,type)
{
}

void CLabel::show() 
{
	CTools::gotoxy(this->startX,this->startY);
	cout<<this->content<<endl; 
}

CLabel::~CLabel()
{
}

8.CEdit.h

#ifndef CEDIT_H
#define CEDIT_H
#include"CtrBase.h"

class CEdit:public CtrBase
{
public :
	CEdit();  
	~CEdit(); 
	CEdit(int x,int y,int w ,int h,char *pcontent,int maxLen,int inputType,int ips,int type);
	void show();
	void keyListen(char ch);//基类写virtual,子类就不写了
private:
	int inputType;  //输入的类型
	int maxLen;     //最大长度
	int ips;        //明文密文
};

#endif

9.CEdit.cpp

#include"CEdit.h"
#include"CTools.h"
#include<iostream>
using namespace std;
#include<conio.h>

CEdit::CEdit():CtrBase()  //基类的构造传参
{
}

//为基类的构造进行传参 关注点:派生类形参的名称
CEdit::CEdit(int x,int y,int w,int h,char *pcontent,
			int maxLen,int inputType,int ips ,int type)
			:CtrBase(x,y,w,h,pcontent,type)
{
	this->maxLen = maxLen;
	this->inputType = inputType;
	this->ips = ips;
}

CEdit::~CEdit()
{
}

void CEdit::show()
{
	CTools::paintWindow(this->startX,this->startY,
				this->width,this->height);
	CTools::gotoxy(this->startX+2+strlen(this->content),this->startY+1);
	memset(this->content,'\0',sizeof(this->content));
    cout<<this->content;	
}

//使用多态 虚函数
//监听控件函数的具体实现
void CEdit::keyListen(char ch)
{
    int i=strlen(this->content);//从字符串原来的长度开始存储
	switch(this->inputType)
	{
	case 0: //数字
		if(ch>='0'&&ch<='9'&&i<this->maxLen)
		{
			if(this->ips==0)
			{
				putch('*');	
			}
			else{
			      putch(ch);
			}
			this->content[i++]=ch;			
		}
		break;
	case 1:  //字母
		if(i<this->maxLen&&((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')))
		{
			if(this->ips==0)
			{
				putch('*');				
			}
			else{				
				putch(ch);
			}
			this->content[i++]=ch;			
		}
		break;
	case 2:  //数字+字母
		if(i<this->maxLen&&((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch>='0'&&ch<='9')))
		{
			if(this->ips==0)
			{
				putch('*');				
			}
			else{				
				putch(ch);
			}
			this->content[i++]=ch;		
		}
		break;
	default:
		break;		
	}
}

10.CButton.h

#ifndef CBUTTON_H
#define CBUTTON_H
#include"CtrBase.h"

class CButton:public CtrBase   
{
public:
	CButton();
	CButton(int x,int y,int w,int h,char *pcontent,int type);
	~CButton();
	void show();	
private:   
};

#endif

11.CButton.cpp

#include"CButton.h"
#include<iostream>
using namespace std;
#include"CTools.h"

CButton::CButton()
{
}

CButton::CButton(int x,int y,int w,int h,char *pcontent,int type)
:CtrBase(x,y,w,h,pcontent,type)
{
}

CButton::~CButton()
{
}

void CButton::show()
{
	CTools::paintWindow(startX,startY,width,height);
	CTools::gotoxy(startX+(width*2-strlen(content))/2-1,startY+1);
	cout<<content<<endl; 
}

12.CWinBase.h

#ifndef CWINBASE_H
#define CWINBASE_H
#include"CtrBase.h"

class CWinBase
{
public:
	CWinBase();
    CWinBase(int x,int y,int w,int h);
	~CWinBase();
	void addControl(CtrBase *ctrl);
	void showWindow();
	int WinRun();
	//在基类声明时加虚  定义时候不加
	virtual int doAction()=0; //窗口切换  纯虚函数的类-抽象类
protected:  
	int startX;
	int startY;
	int width;
	int height;
	int ctrlCount;
	CtrBase *ctrlArr[10];
	int focusIndex;      //按下回车键按钮的下标
};

#endif

13.CWinBase.cpp

#include"CWinBase.h"
#include"CTools.h"
#include<iostream>
using namespace std;
#include"CEdit.h"//static_cast<CEdit*>

CWinBase::CWinBase()
{
	this->startX = 0;
	this->startY = 0;
	this->width = 0;
	this->height = 0;
	this->ctrlCount = 0;
}

CWinBase::CWinBase(int x,int y,int w,int h)
{
	this->startX = x;
	this->startY = y;
	this->width = w;
	this->height = h;
	this->ctrlCount = 0;
}

CWinBase::~CWinBase()
{

}

//添加控件
void CWinBase::addControl(CtrBase *ctrl)//统一基类指针进行接收
{
	//派生类指针赋值给基类指针 范围缩小了
	this->ctrlArr[this->ctrlCount++] = ctrl;
	//后面执行基类的show函数
}

void CWinBase::showWindow()
{
	//显示大框  显示每个控件
	CTools::paintWindow(this->startX,this->startY,this->width,this->height);
	for(int i=0;i<this->ctrlCount;i++)
	{
		//基类指针操作派生类成员函数
		//通过基类指针 或 引用调用虚函数  触发动态绑定
		this->ctrlArr[i]->show();  //执行基类的show函数	
	}
}

int CWinBase::WinRun()
{
	int i=0,key=0;
	for(i=0;i<this->ctrlCount;i++)
	{
		if(this->ctrlArr[i]->getType()==EDIT||this->ctrlArr[i]->getType()==BUTTON)
		{
			CTools::gotoxy(this->ctrlArr[i]->getX()+2,this->ctrlArr[i]->getY()+1);
			break;
		}
	}
	while(1)
	{
		key=CTools::getkey();
		switch(key){
		case KEY_DOWN://向下按键  查找下一个编辑框 按钮
			i++;//按键数组下标越界
			if(i==this->ctrlCount)
			{
				i=0;//为了避免下标越界 从头开始对控件结构体数组找编辑框 按钮
			}
			for(;i<this->ctrlCount;i++)
			{
				if(this->ctrlArr[i]->getType()==EDIT)
				{
					CTools::gotoxy(this->ctrlArr[i]->getX()+2+strlen(this->ctrlArr[i]->getContent())
				,this->ctrlArr[i]->getY()+1);
					break;
				}
				else if(this->ctrlArr[i]->getType()==BUTTON)
				{
					CTools::gotoxy(this->ctrlArr[i]->getX()+(this->ctrlArr[i]->getW()-strlen(this->ctrlArr[i]->getContent())/2)
				,this->ctrlArr[i]->getY()+1);
					break;
				}
			}
			break;
		case KEY_UP:
			i--;
			if(i==-1)  //从后往前找 数组起始0 i--为-1 数组下标由大到小 (控件数组下标0位置)
			{
				i=this->ctrlCount-1;  //控件个数(控件结构体数组下标最大)-1 (控件数组下标ctrlCount位置)
			}
			for(;i>0;i--)
			{
				if(this->ctrlArr[i]->getType()==EDIT)
				{
					CTools::gotoxy(this->ctrlArr[i]->getX()+2+strlen(this->ctrlArr[i]->getContent())
				,this->ctrlArr[i]->getY()+1);
					break;
				}
				else if(this->ctrlArr[i]->getType()==BUTTON)
				{
					CTools::gotoxy(this->ctrlArr[i]->getX()+(this->ctrlArr[i]->getW()-strlen(this->ctrlArr[i]->getContent())/2)
				,this->ctrlArr[i]->getY()+1);
					break;//停止
				}
				if(i==0)  //第一个 若第一个不是编辑框 按钮
				{
					i=this->ctrlCount;  //就从最后一个往前查找 for循环中有i--,不用再-1	
				}
			}
			break;
		case KEY_ENTER:
			if(this->ctrlArr[i]->getType()==BUTTON)
			{
				this->focusIndex=i;
				//返回切换到的界面的下标
				return doAction();
			}
			break;
		default:   //其他字符(不是按键)并且当前控件是编辑框
			if(this->ctrlArr[i]->getType()==EDIT)
			{
				//父类指针不能操作子类的函数
				//解决:把父类指针强制转换为子类指针(不安全)
			    //(static_cast<CEdit*>(this->ctrlArr[i]))->keyListen(key);
			
				//解决:对应控件监听函数用虚函数
				this->ctrlArr[i]->keyListen(key);
			}
			break;
		}
	}
}

/*
每一个子类各不相同,使用纯虚函数,全部由子类实现各自的方法
void CWinBase::doActon()
{
}
*/

14.CLogin.h

#ifndef CLOGIN_H
#define CLOGIN_H
#include "CLabel.h"
#include"CEdit.h"
#include"CButton.h"
#include"CWinBase.h"

class CLoginWin:public CWinBase
{
public :
	CLoginWin();
	CLoginWin(int x,int y,int w,int h);
	~CLoginWin();
	int doAction();
private:
    CLabel *title,*labName,*labPwd; //文本
	CButton *btnlogin ,*btnexit;    //按钮
	CEdit *editName,*editPwd;       //编辑框
};

#endif

15.CLogin.cpp

#include"CLogin.h"
#include "CTools.h"
#include<iostream>
using namespace std;

CLoginWin::CLoginWin():CWinBase()
{
}

CLoginWin::CLoginWin(int x,int y,int w,int h)
:CWinBase(x,y,w,h)
{
	this->title = new CLabel(36,8,20,2,"点菜系统",LABEL);
	this->labName = new CLabel(26,11,10,2,"用户名:",LABEL);
	this->labPwd = new CLabel(26,15,10,2,"密码:",LABEL);

//int x,int y,int w,int h,char *pcontent,
//int maxLen,int inputType,int ips
	this->editName = new CEdit(34,10,10,3,"",8,2,1,EDIT);
	this->editPwd = new CEdit(34,14,10,3,"",6,2,0,EDIT);

	this->btnlogin = new CButton(25,18,6,3,"登录",BUTTON);
	this->btnexit = new CButton(45,18,6,3,"退出",BUTTON); 
	
	this->addControl(this->title);
	this->addControl(this->labName);
	this->addControl(this->labPwd);
	this->addControl(this->editName);
	this->addControl(this->editPwd);
	this->addControl(this->btnlogin);
	this->addControl(this->btnexit);
}

CLoginWin::~CLoginWin()
{	
}

//基类不做事(每个派生类实现都不一样) 使用纯虚函数  子类自行解决 
//派生类实现基类的纯虚函数--重写
int CLoginWin::doAction()
{
	switch(this->focusIndex)
	{
	case 5:
        return 1;
		break;
	case 6:
		return 0;
		break;
	default:
		break;
	}
	return 0;
}

16.CIndexWin.h

#ifndef CINDEXWIN_H
#define CINDEXWIN_H
#include"CWinBase.h"//继承窗口基类
#include"CButton.h"
#include "CLabel.h"
#include"CEdit.h"

class CIndexWin:public CWinBase
{
public:
	CIndexWin();
	~CIndexWin();
	CIndexWin(int x,int y,int w,int h);
	int doAction();
protected:
private:
    CLabel *titleguan;
	CButton *btntaizhuo ,*btncaipu,*btnrenyuan,*btnzhuxiao,*btntuichu;
};

#endif

17.CIndexWin.cpp

#include"CIndexWin.h"
#include"CTools.h"
#include<iostream>
using namespace std;

CIndexWin::CIndexWin():CWinBase()
{
}

CIndexWin::~CIndexWin()
{
}

CIndexWin::CIndexWin(int x,int y,int w,int h)
:CWinBase(x,y,w,h)
{
    this->titleguan = new CLabel(21,7,10,2,"管理员界面",LABEL); //0
	
	this->btntaizhuo = new CButton(19,9,8,3,"台桌管理",BUTTON); //1
	this->btncaipu = new CButton(19,12,8,3,"菜谱管理",BUTTON);  //2
	this->btnrenyuan = new CButton(19,15,8,3,"人员管理",BUTTON);//3
	this->btnzhuxiao = new CButton(19,18,8,3,"注销",BUTTON);    //4
	this->btntuichu = new CButton(19,21,8,3,"退出",BUTTON);     //5
	
	this->addControl(this->titleguan);
   	this->addControl(this->btntaizhuo);
	this->addControl(this->btncaipu);
	this->addControl(this->btnrenyuan);
	this->addControl(this->btnzhuxiao);
	this->addControl(this->btntuichu);	 
}

int CIndexWin::doAction()
{
	switch(this->focusIndex)
	{
	case 5:       
		return 0;  //到初始界面
	default:
		break;	
	}
	return 0;//0
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

举报

相关推荐

0 条评论