Review cpp day10

回顾:
Review cpp day01
Review cpp day02
Review cpp day03
Review cpp day04
Review cpp day05
Review cpp day06
Review cpp day07
Review cpp day08
Review cpp day09

二十三、运行时的类型信息//了解

1、typeid操作符

#include <typeinfo>
typeid(类型/对象);
  • 返回typeinfo的对象,用于描述类型信息,里面包含一个name的成员函数,可以将类型信息转化为字符串形式。
  • typeinfo提供了对“==”和“!=”操作符重载的支持,通过它们可以直接进行类型之间的比较。

06typeid.cpp

#include <iostream>
#include <typeinfo>
#include <cstring>
using namespace std;

class X{
	virtual void foo(){}
};
class Y:public X{
	void foo(){}
};
class Z:public X{
	void foo(){}
};

void func(X& x){
	//if(!strcmp(typeid(x).name(), "1Y")){
	if(typeid(x) == typeid(Y)){
		cout << "针对Y对象处理" << endl;
	}
	//else if(!strcmp(typeid(x).name(), "1Z")){
	else if(typeid(x) == typeid(Z)){
		cout << "针对Y对象处理" << endl;
	}
	else{
		cout << "针对X对象处理" << endl;
	}
}
int main(void){
	int a;
	cout << typeid(int).name() << endl;//i
	cout << typeid(a).name() << endl;//i
	
	int arr[10];
	cout << typeid(arr).name() << endl;//A10_i;

	int* p;
	cout << typeid(p).name() << endl;//Pi
	
	int *arr1[10];
	int (*arr2)[10];
	cout << typeid(arr1).name() << endl;//A10_Pi
	cout << typeid(arr2).name() << endl;//PA10_i

	cout << typeid(int (*)(char)).name() << endl;//PFicE

	cout << typeid(Y).name() << endl;//1Y

	Y y;
	Z z;
	X x;
	func(y);
	func(z);
	func(x);

	return 0;
}

在这里插入图片描述

2、动态类型转换操作符

  • 语法:目标类型变量 = dynamic_cast<目标类型>(源类型变量);
  • 适用场景:用于具有多态继承关系的父子类指针或引用的显式转换。

注: 在转换过程中,会检查目标对象的类型和期望转换的类型是否一致,如果一致转换成功,否则转换失败。如果转换的是指针,返回NULL表示失败,如果转换的是引用,抛出“bad_cast”异常表示转换失败。

07dynamic.cpp

#include <iostream>
using namespace std;

class A{
	virtual void foo(void){}
};
class B:public A{
	void foo(void){}
};
class C:public A{
	void foo(void){}
};
int main(void){
	B b;
	A* pa = &b;
	//B* pb = static_cast<B*>(pa);//合理
	//C* pc = static_cast<C*>(pa);//编译器能编译通过,但这种转换不合理
	B* pb = dynamic_cast<B*>(pa);
	//C* pc = dynamic_cast<C*>(pa);//error,可以发现转换不合理而报错
	cout << "pa=" << pa << endl;
	cout << "pb=" << pb << endl;

	A& ra = b;
	//C& rc = dynamic_cast<C&)(ra);//error,可以发现转换不合理而报错
	
	cout << "pc=" << pc << endl;//NULL
	return 0;
}

二十四、异常(EXception)

1、开发中常见的错误

  • 1)语法错误
  • 2)逻辑错误
  • 3)功能错误
  • 4)设计缺陷
  • 5)需求不符
  • 6)环境异常
  • 7)操作不当

2、传统C中错误处理机制//了解

  • 1)通过返回值表示错误
    • 优点:函数调用路径中所有的局部函数对象都能被正确地析构,不会发生内存泄漏。
    • 缺点:错误处理的流程比较复杂,需要逐层判断,代码臃肿。

01error.cpp

#include <iostream>
#include <cstdio>
using namespace std;


class A{
publuc:
	A(void){
		cout << "A::A()" << endl;
	}
	~A(void){
		cout << "A::~A()" << endl;
	}
};
int func3(void){
	A a;
	FILE* fp = fopen("xx.txt", "r");
	if(fp  = NULL){
		cout << "文件打开失败!" << endl;
		return -1;
	}
	//...
	fclose fp;
	fp = NULL;
}
int func2(void){
	A = a;
	if(func3() == -1){
		return -1;
	}
	//...
	return 0;
}
int func1(void){
	A a;
	if(func2 == -1){
		return -1;
	}
	//...
	return 0;
}
int main(void){
	if(func1 == -1){
		return -1;
	}
	return 0;
}
A::A()
A::A()
A::A()
文件打开失败!
A::~A()
A::~A()
A::~A()
  • 2)通过远程跳转处理错误
    • 优点:不需要逐层判断,一步到位的错误处理,代码精炼。
    • 缺点:函数调用路径中的局部对象失去被析构的机会,有内存泄漏的风险。

02error.cpp

#include <iostream>
#include <cstdio>
#include <csetjmp>
using namespace std;

jmp_buf g_env;

class A{
publuc:
	A(void){
		cout << "A::A()" << endl;
	}
	~A(void){
		cout << "A::~A()" << endl;
	}
};
int func3(void){
	A a;
	FILE* fp = fopen("xx.txt", "r");
	if(fp  = NULL){
		longjmp(g_env, -1);
	}
	//...
	fclose(fp);
	fp = NULL;
}
int func2(void){
	A  a;
	func3();
	//...
	return 0;
}
int func1(void){
	A a;
	func2();
	//...
	return 0;
}
int main(void){
	if(setjmp(g_env) == -1){
		cout << "文件打开失败" << endl;
	}
	func1();
	return 0;
}
A::A()
A::A()
A::A()
文件打开失败!

3、C++异常机制

  • 结合两种传统错误处理的优点,同时避免它们的缺点,在形式实现一步到位的错误处理,同时保证所有的局部对象得到正确的析构。

4、异常语法

  • 1)异常抛出: throw 异常对象;

eg:

	throw -1;
	thow "error";
	//--------------------
	class FileError();
	throw FileError();
  • 2)异常捕获
	try{
		可能引发异常的语句;
	}
	catch(异常类型1){
		针对异常类型1的处理;
	}
	catch(异常类型2){
		针对异常类型2的处理;
	}
	catch(...){
		针对其他异常类型的处理;
	}

03error.cpp

#include <iostream>
#include <cstdio>
using namespace std;

class A{
public:
	A(void){
		cout << "A::A()" << endl;
	}
	~A(void){
		cout << "A::~A()" << endl;
	}
};
class FileError{
public:
	FileError(const string& file, int line){
		cout << "出错位置:" << file << "," << line << endl;
	}
};
int func3(void){
	A a;
	FILE* fp = fopen("xx.txt", "r");
	if(fp == NULL){
		throw FileError(__FILE__, __LINE__);
		throw -1;//抛出异常
		cout << "test1" << endl;
	}
	//...
	fclose(fp);
	fp = NULL;
	return 0;
}
int func2(void){
	A a;
	func3();
	cout << "test2" << endl;
	//...
	return 0;
}
int func1(void){
	A a;
	func2();
	cout << "test3" << endl;
	//...
	return 0;
}
int main(void){
	try{
		func1();	
		//.....
	}
	catch(int ex){
		if(ex == -1){
			cout << "文件打开失败" << endl;
			return -1;
		}
	}
	catch(FileError& ex){
		cout << "文件打开失败!" << endl;
		return -1;
	}

	return 0;
}
A::A()
A::A()
A::A()
出错位置:03exception.cpp,21
A::~A()
A::~A()
A::~A()
文件打开失败!

注: 子类的异常处理应该写在基类处理的前面,否则会发生向上造型提前捕获异常。(catch子句根据异常的类型自上而下顺序匹配,而不是最匹优配,所以对子类类型的异常捕获不要放在对基类类型异常捕获的后面,否则前者将被后者提前截取。)

04exception.cpp

#include <iostream>
using namespace std;

class ErrorA{};
class ErrorB:public ErrorA{};

int main(void){
	try{
		//...
		throw ErrorA();
		throw ErrorB();
		//...
	}
	catch(ErrorB& ex){
		cout << "捕获到ErrorB的异常!" << endl;
		return -1;
	}
	catch(ErrorA& ex){
		cout << "捕获到ErrorA的异常!" << endl;
		return -1;
	}
	return 0;
}

5、函数异常说明

  • 1)定义: void func(形参表) throw(异常类型表){//函数体}
  • 2)函数的异常说明是一种承诺,表示该函数所抛出的异常不会超出所说明的范围,如果抛出了异常以外的类型,该异常无法正常捕获,而会被系统捕获终止进程。
  • 3)函数异常说明的两种极端形式
    • 不写异常说明,表示可以抛出任何异常;
    • 空异常说明,throw(),表示不会抛出任何异常。
  • 4)函数的声明和定义如果分开写,要保证异常说明一致。

05exception.cpp

#include <iostream>
using namespace std;

class FileError{};
class MemoryError{};
//函数的声明
void func(void) throw(int, FileError, MemoryError);
//函数的定义
void func(void) throw(int, FileError, MemoryError){
	//...
	throw FileError();
}
int main(void){
	try{
		func();
	}
	catch(int ex){
		cout << "int类型异常" << endl;
		return -1;
	}
	catch(FileError& ex){
		cout << "FileError类型异常" << endl;
		return -1;
	}
	catch(MemoryError& ex){
		cout << "MemoryError类型异常" << endl;
		return -1;
	}
	return 0;
}
  • 5)如果基类中虚函数带有异常说明,那么该函数在子类中的覆盖版本不能比基类抛出更多的异常,否则将会因为“放松throw限定”导致编译失败。

06exception.cpp

#include <iostream>
using namespace std;

class Base{
public:
	virtual void func(void)throw(int, char){}
	virtual ~Base(void) throw(){}
};
class Derived:public Base{
	void func(void) throw(int,char){}
	//void func(void) throw(int){}//ok
	//void func(void) throw(int,char,double){}//error
	~Derived(void) throw(){}
	//~Derived(void){}//error
};
int main(void){
	return 0;
}

6、标准异常类:exception

class exception{
public:
	exception() throw() {}
	virtual ~exception() throw() {}
	virtual const char* what() const throw();
};

07exception.cpp

#include <iostream>
using namespace std;

class FileError:public exception{
public:
	~FileError(void)throw(){};
	const char* what(void) const throw(){
		cout << "针对文件错误的处理" << endl;
		return "FileError";
	}
};
class MemoryError:public exception{
public:
	~MemoryError(void)throw(){};
	const char* what(void) const throw(){
		cout << "针对内存错误的处理" << endl;
		return "MemoryError";
	}
};
void func() throw(FileError, MemoryError){
	throw FileError();
	//throw MemoryError();
}
int main(void){
	try{
		//char* p = new char[0xffffffff];
		func();
	}	
	catch(exception& ex){
		cout << ex.what() << endl;
	}
	return 0;
}

7、构造和析构函数中的异常

  • 1)构造函数可以抛出异常,但是对象将会被不完整构造,这样对象析构函数无法正常被执行;所以在构造函数抛出异常之前,需要手动地销毁在异常产生之前所分配的动态资源。
  • 2)析构函数不要抛出异常。

08exception.cpp

#include <iostream>
#include <cstdio>
using namespace std;

class A{
public:
	A(void){
		cout << "A::A()" << endl;
	}
	~A(void){
		cout << "A::~A()" << endl;
	}
};
class B{
public:
	B(void){
		m_a = new A;
		FILE* fp = fopen("xx.txt", "r");
		if(fp == NULL){
			delete m_a;//手动释放动态资源
			throw -1;
		}
		//...
		fclose(fp);
	}
	~B(void){
		delete m_a;
		m_a = NULL;
	}
private:
	A* m_a;
};
int main(void){
	try{
		B b;
	}
	catch(int ex){
		cout· << "捕获到异常" << endl;
		return -1;
	}
	return 0;
}

09exception.cpp

#include <iostream>
using namespace std;

class A{
public:
	void func(void){
		throw -1;
	}
	~A(void){
		throw -2;//析构抛出异常,难以处理
	}
};
int main(void){
	try{
		A a;
		a.func();
	}
	catch(int ex){
		cout << "捕获到异常:" << ex << endl;
		return -1;
	}
	return 0;
}

二十五、I/O流 //了解

1、主要的I/O流

			                     ios
		                  /	  	          \
	             istream		       osteam
 	       /       |	     \	     /      |	 \
  istrstream	 ifstream   iostream    ofstream  ostrstream
   sscanf()  fscanf()	  /         \  fprintf()  sprintf()
		         strestream          fstream        
                                                

2、格式化I/O

  • 1)格式化函数(成员函数)

eg:

	cout << e0/3.0 << endl;//3.33333
	------------------------------------
	cout.precision(10);
	cout << 10/3.0 << endl;//3.333333333

10format.cpp

#include <iostream>
using namespace std;

int main(void){
	cout << 10/3.0 << endl;//3.33333
	cout.precision(10);//精度
	cout << 10/3.0 << endl;//3.333333333

	cout << '[' ;
	cout.width(10);//域宽
	cout.fill('*');//空白位置填充“*”
	cout.setf(ios::showpos);//显示符号位
	cout.setf(ios::internal);//内插对齐,符号为靠左,数值位靠右
	cout <<1234 << ']' << endl;//[+*****1234]
}
  • 2)流控制符(全局函数)
    eg:
	cout << e0/3.0 << endl;//3.33333
	------------------------------------
	cout.precision(10);
	cout << setprecision(10) << 10/3.0 << endl;//3.333333333

11format.cpp

#include <iostream>
#include <iomanip>//使用流控制符添加的头文件,如最后的setw、setfill、showpos等
using namespace std;

int main(void){
	cout << 10/3.0 << endl;//3.33333
	//cout.precision(10);//精度
	//cout << 10/3.0 << endl;//3.333333333
	cout << setprecision(10) << 10/3.0 << endl;

	/*
	cout << '[' ;
	cout.width(10);//域宽
	cout.fill('*');//空白位置填充“*”
	cout.setf(ios::showpos);//显示符号位
	cout.setf(ios::internal);//内插对齐,符号为靠左,数值位靠右
	cout <<1234 << ']' << endl;//[+*****1234]*/

	//使用流控制符
	cout << "[" << setw(10) << setfill('*') << showpos << 
		internal << 1234 << "]" << endl;
	//setw:设置域宽
	//setfill:设置空白填充字符
	//showpos:显示符号位
	//internal:内插方式
}

3、字符串流

#include <strstream>//过时
istrstream、ostrstream、strstream

#include <sstream>//推荐
istringstream,读操作(sscanf)
ostringstream,写操作(sprintf)
stringstream,读写

12string.cpp

#include <iostream>
#include <sstream>
using namespace std;

int main(void){
	int i = 123;
	double d = 4.56;
	char s[] = "abcdef";
	/*
	下面的代码相当于如下的c风格的代码
	char buffer[100] = {0};
	sprintf(buffer,"%d %g, %s", i, d, s);	
	*/
	ostringstream oss;
	oss << i << ' ' << d << ' '  << s;
	cout << oss.str() << endl;

	/*
	char buffer[] = "321 6.54 hello";
	sscanf(buffer, "%d %lf %s", &i, &d, s);
	*/
	istringstream iss;
	iss.str("321 6.56 hello");
	iss >> i >> d >> s;
	cout << i << ',' << d << ',' << s << endl;
	return 0;
}

在这里插入图片描述

4、文件流

#include <fstream>
ifstream,读文件(fscanf)
ofstream,写文件操作(fprintf)
fstream,读写操作

13file.cpp

#include <iostream>
#include <fstream>
using namespace std;

int main(void){
	//ios:out以写的方式打开文件,不存在则创建
	ofstream ofs("file.txt"/*ios::out*/);
	ofs << 1234 << ' ' << 56.78 << ' ' << "helloworld!" << endl;
	ofs.close();
	
	//ios::in以读方式打开文件
	ifstream ifs("file.txt"/*ios::in*/);
	int i;
	double d;
	string s;
	ifs << i << d << s;
	cout << i << ' ' << d << ' ' <<  s << endl;
	ifs.close();
	return 0;
}

5、二进制I/O

  • //写操作,fwrite
    ostream& ostream::write(const char* buffer, size_t num);

  • //读操作, fread
    istream& istream::read(char* buffer, streamsize num);

14binary.cpp

#include <iostream>
#include <fstream>
using namespace std;

int main(void){
	ofstream ofs("last.txt");
	char wbuf[] = "C++终于结束了!";
	ofs.write(wbuf, sizeof(wbuf));
	ofs.close();
	
	ifstream ifs("last.txt");
	char rbuf[100] = {0};
	ifs.read(rbuf,sizeof(rbuf));
	cout << "读到数据" << rbuf << endl;
	ifs.close();

	return 0;
}

补充知识

#include <iostream>

using namespace std;

class Data{
public:
	//explicit该有有参构造不允许隐式转换
	explicit Data(int n):num(n){
		cout << "Data::Data(int)" << endl;
	}
	~Data(void){
		cout << "Data::~Data(void)" << endl;
	}
	void showNum(void){
		cout << "num=" << num << endl;
	}
private:
	int num;
};
int main(void){
	//隐式转换
	//Data data = 10;//ecplicit 该有参构造函数 不允许 隐式转换
	Data data(10);//等价Data data = Data(10);显式调用有参构造
	data.showNum();
	return 0;
}

扩展练习V8.0:实现企业员工管理系统

  • 需求:
    • 1)使用多态语法改善继承结构
    • 2)增加销售员和销售主管类
  • 销售员:
    • 提成比率(百分比)
    • 绩效工资 = 销售额度(输入) * 提成比率
  • 销售主管:
    • 绩效工资 = (销售员绩效 + 经理绩效)/ 2
                      员工(Employee)
                 	/         |	     \
                   技术员   经理	     销售员
                 	\     /   \      /
                   技术主管     销售主管
  • 提示:
	void printInfo(){
		printBasic();//打印公有信息
		printExtra();//打印特有信息
	}
	void calSalary(){
		//总工资 = 基本工资 + 绩效工资
		calBasic() + calMerit();
	}
 
	class 员工(Employee){
	public:
		void printInfo{
			打印公有信息();
			打印特有信息();//声明为虚函数
		}
	};
	class 技术员: public 员工{
		打印特有信息();//对基类版本形成有效覆盖
	};
	class 经理: public 员工{
		打印特有信息();//对基类版本形成有效覆盖
	};
	技术员对象.printInfo();
	经理对象.printInfo();

Employee.h

#ifndef __EMPLOYEE_H__
#define __EMPLOYEE_H__


#include <iostream>
#include <cstdio>
using namespace std;

class Employee{
public:
	Employee(const string& name, double salary);
	~Employee(void);
	void printInfo(void)const;
protected:
	void printInfo(void)const;//公有信息
	virtual void printExtra(void)const;//特有信息
public:
	//计算工资
	void claSalary(void);
protected:
	double calBasic(void);//基本工资
	virtual double calMerit(void);//绩效工资
public:
	void setId(int id);
	void setName(const string& name);
	void setSalary(double salary);
	void saveInfo(void)const;

	//根据员工对象的id和参数id比较,是否相等
	bool operator==(int id)const;
	bool operator!=(int id)const;

	friend ostream& operator<<(ostream& os, const Employee& emp);
private:
	//禁止拷贝构造函数和拷贝复制
	Employee& operator = (const Employee&);
	Employee(const Employee&);
private:
	int m_id;//工号
	string m_name;//姓名
	double m_salary;//工资
	FILE* file;//保存员工信息指针
	double m_attend;//出勤率
public:
	//获取员工人数
	static const int& getEmployeeCount(void);
private:
	static int m_count;//记录员工人数
};

#endif //__EMPLOYEE_H__

Employee.cpp

#include "Employee.h"
Employee::Employee(const string& name, double salary)
		:m_name(name), m_saraly(salary){
	//读取ID
	FILE* fp = fopen("id.txt", "r+");
	fscanf(fp, "%d", &m_id);
	//将文件读写指针定位到文件头
	fseek(fp, 0, SEEL_SET);
	//ID+1, 再保存回id.txt
	fprintf(fp, "%d", m_id+1);
	//关闭id.txt
	fclose(fp);

	//将ID转换为字符串
	char filename[20] = {0};
	sprintf(filename, "%d", m_d);
	//根据id创建文件保存当前员工信息
	file = fopen(filename, "w");
	//保存员工信息
	saveInfo();
	
	//记录员工人数
	++m_count;
	//保存与纳贡人数
	FILE* fp2 = fopen("count.txt", "w");
	fprintf(fp2, "%d", m_count);
	fclose(fp2);
}
Employee::~Employee(void){
	fclose(file);
	file =NULL;
}
Employee::Employee(const Employee& that){
	char filename[20] = {0};
	sprintf(filename, "%d", that.m_id);
	file = fopen(filename, "r+");
	m_id = that.m_id;
	m_name = that.m_name;
	m_salary = that.m_salary;
}
void Employee::printInfo(void)const{
	printBasic();
	printExtra();
}
void Employee::printBase(void)const{
	cout << "姓名:" << m_name << endl;
	cout << "工号:" << m_id << endl;
	cout << "基础工资:" << m_salary << endl; 
}
void Employee::printExtra(void)const{
	cout << "职位:普通员工" << endl;
}
void Eployee::calSalary(void){
	double salary = calBasic() + calMerir();
	cout << "总工资为:" << salary << endl;
}
double Employee::calBasic(void){
	cout << "请输入出勤天数:";
	int days;
	cin >> days;
	m_attent = days/23.0;//计算出勤率
	return m_salary * m_attend;
	
}
double Employee::calMerit(void){
	return m_salary * m_attend / 2;
}
void Employee::setid(int){
	if(id < 10000){
		cout << "无效的工号" << endl;
	}
	else{
		m_id = id;
	}
}
void Employee::setName(const string& name){
	if(name.size() > 20){
		cout << "无效的姓名" << endl;
	}
	else{
		m_name = name;
	}
}
void Employee::setSalary(double){
	if(salary < 0){
		cout << "无效工资" << endl;
	}
	else{
		m_salary = salary;
	}
}
void Employee::saveInfo(void)const{
	fseek(file, 0, SEEK_SET);
	fprintf(file, "%d %s %g", m_id, m_name.c_str(), m_salary);
}
//静态成员需要在类的外部单独定义和初始化
int Employee::m_count = 0;

count int& Employee::getEmployeeCount(void){
7this	FILE* fp = fopen("count.txt", "r");
	//加载员工人数
	fscanf(fp, "%d", &m_count);
	fclose(fp);
	return m_count;
}
//根据员工对象的id和参数id比较,是否相等
bool Employee::operator==(int id)const{
	if(m_id ==id){
		return true;
	}
	else{
		return false;
	}
}
bool Employee::operator!=(int id)const{
	return !(*this == id);//函数复用
}
//全局函数
ostream& operator<<(ostream& os, const Employee& emp){
	os << "Employee(" << emp.m_id << "," << emp.m_name << em.m_salary << ")";
	return os;
}

Technician.h

#ifndef __TECHNICIAN_H__
#define __TECHNICIAN_H__

#include "Employee.h"

class Technician: public Employee{
public:
	Technician(const string& name,double salary, double allow);
	void printInfo(void)const;
	void printExtra(void)const;
	void calSalary(void);
	double calMerit(void);
	friend ostream& operator<<(ostream& os, const Technician& tech);
private:
	double m_allow;//研发津贴
};

#endif //__TECHNICIAN_H__

Technician.cpp

#include <Technician.h>

Technician::Technician(const string& name, double salary, double allow):
		Employee(name, salary), m_allow(allow){
	fprintf(file, "%g", m_allow);
}
void Technician::printInfo(void)const{
	printBasic();
	printExtra();
}
void Technician::printExtra(void)const{
	cout << "职位:技术员" << endl;
	cout << "研发津贴:" << m_allow << endl;
}
void Technician::calSalary(void){
	double salary = calBasic() + calMerit();
	cout << "总工资为:" << salary << endl;
}
void Technician::calMerit(void)const{
	cout << "请输入进度因数:";
	double factor;
	cin >> factor;
	return 23 * 8 * m_attend * m_allow * factor;
}
ostream& operator<<(ostream& os, const Technician& tech){
	os << "Technician(" << tech.name << "," << tech.m_id << ")";
}

Manager.h

#ifndef __MANAGER_H__
#define __MANAGER_H__

#include "Employee.h"

class Manager: public Employee{
public: 
	Manager(const string& name, double salary, double m_bonus);
	void printInfo(void)const;
	void printExtra(void)const;
	void calSalary(void);
	double calMerit(void);
private:
	double m_bonus;//绩效奖金
};

#endif //__MANAGER_H__

Manager.cpp

#include "Manager.h"

Manager::Manager(const string& name, double salary, double bonus):
		Employee(name, salary), m_bonus(bonus){
	//保存经理的绩效工资
	fprintf(file, "%g", m_bonus);	
}
void Manager::printfInfo(void)const{
	printBasic();
	printExtra();
}
void Manager::printExtra(void)const{
	cout << "职位:经理" << endl;
	cout << "绩效工资:" << m_bonus << endl;
}
void Manager::calSalary(void){
	double salary = calBasic() + calEerit();
	cout << "总工资为:" << salary << endl;
}
void Manager::calEerit(void){
	cout << "请输入j绩效因数:";
	double factor;
	cin >> factor;
	return m_bonus * factor;
}

CTO.h

#ifndef __CTO_H__
#define __CTO_H__
#include "Maneger.h"
#include "Technician.h"

class CTO:public Technician, public Manager{
public:
	CTO(const string& name, double salary, double allow, double bonus);
	void printInfo(void)const;
	void printExtra(void)const;
	void calSalary(void);
	double calMerit(void);
};
#endif //__CTO_H__

CTO.cpp

#include "CTO.h"

CTO::CTO(const string& name, double salary,double allow, double bonus):
	Technician(name, salary, allow), Manager(name, salary, bonus), 
	Employee(name, salary){}
void CTO::printInfo(void)const{
	printBasic();
	printExtra();
}
void CTO::printExtra(void)const{
	cout << "职位:技术主管" << endl;
	cout << "研发津贴:" << m_allow << endl;
	cout << "绩效奖金:" << m_bonus << endl;
}
void CTO::calSalary(void){
	double salary = calSalary + calMerit();
	cout << "总工资为:" << salary << endl;
}
double CTO::calMerit(void){
	return (Technician::calMerit() + Manager::calMerit()) / 2; 
}

SalesPerson.h

#ifndef __SALESPERSON_H__
#define __SALESPERSON_H__

#include "Employee.h"

class SalesPerson:virtual public Employee{
public:
	SalesPerson(const string& name, double salary, double percent);
protected:
	void printExtra(void)const;
	double calMerit(void);
	double m_percent;//百分比
};

#endif //__SALESPERSON_H__

SalesPerson.cpp

#include "SalesPerson.h"

SalesPerson::SalesPerson(const string& name, double salary, double percent):
		Employee(name, salary), m_percent(percent){
	//保存员工绩效信息
	fprintf(file, "%g", m_percent);
}
void SalesPerson::printExtra(void){
	cout << "职位:销售员" << endl;
	cout << "提成比率:" << m_percent << endl;
}
double Salesperson::calMerit(void)const{
	cout << "请输入销售额度:";
	double sales;
	cin << sales;
	return sales * m_percent; 
}

COO.h

#ifndef __COO_H__
#define __COO___

#include "SalesPerson.h"
#include "Manager.h"

class COO::opublic Salesperson, public Manager{
public:
	COO(const string& name, double salary, double percent, double bonus);
protected:
	void printExtra(void)const;
	double calMerit(void);
}

#endif //__COO_H__

COO.cpp

#include "COO.h"

COO::COO(const string& name, double salary, double percent, double bonus):
	SalesPerson(name, salary, percent), Manager(name, salary, bonus), Employee(name, salary){}

void COO::printExtra(void)const{
	cout << "职位:销售主管" << endl;
	cout << "提成比率:" << m_percent << endl;
	cout << "绩效工资:" << m_bonus << endl;
}

double COO::calMerit(void){
	//销售员+经理 / 2
	return (SalesPerson::calMerit() + Manager::calMerit()) / 2;
}

main.cpp

#include "Employee.h"
#include <unistd.h>
#include <cstdio>
#include <cstdlib>
void init(void){
	if(access("id.txt", F_OK) == -1){
		FILE* fp = fopen("id.txt", "w");//记录工号
		if(fp == NULL){
			perror("fopen"),exit(-1);
		}
		fprintf(fp, "%d", 10001);
		fclose(fp);
	}
	if(access("count.txt", F_OK) == -1){
		FILE* fp = fopen("count.txt", "w");//记录人数
		if(fp == NULL){
			perror("fopen"),exit(-1);
		}
		fprintf(fp, "%d", 0);
		fclose(fp);
	}
	else{
		//加载员工人数
		Employee::getEmployeeCount();
	}
}

int main(void){
	init();
	Employee emp("张三", 6600);
	//emp.printInfo();
	cout << emp << endl;
	emp.calSalary();
	cout << "======================" << endl;
	
	Technician tech("孔明", 8800, 30);
	//tech.printInfo();
	cout << tech << endl;
	tech.calSalary();
	cout << "======================" << endl;

	Manager manager("刘备", 12000, 5000);
	manager.printInfo();
	manager.calSalary();
	cout << "======================" << endl;
	
	CTO cto("司马懿", 16000, 30, 5000);
	cto.printInfo();
	cto.calSalary();
	cout << "当前员工人数:" << Employee::getEmployeeCount() << endl;
	cout << "======================" << endl;
	
	SalesPerson sale("周瑜", 5000, 0.05);
	sale.printInfo();
	sale.calSalary();
	cout << "======================" << endl;

	COO coo("孙权", 18000, 0.05, 5000);
	coo.printInfo();
	coo.calSalary();
	cout << "======================" << endl;
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值