回顾:
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;
}