对研究生和本科生进行统计,并计算成绩,使用一个基本类表示本科生的相关信息,研究生继承本科生公共接口,在通过一个接口类进行相应操作,从而封装学生信息
两个类头文件
#ifndef _grad_h
#define _grad_h
#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
#include"grade_deal.h"
class Grad{
friend class Student;
std::string n;
protected:
double midterm,final;
std::vector<double> homework;
std::istream& read_common(std::istream&);
virtual Grad* clone() const {return new Grad(*this);}
public:
Grad():midterm(0),final(0) { }
Grad( std::istream& is) {read(is); }
virtual ~Grad() { }
virtual std::istream& read( std::istream&);
virtual double grade()const {return ::grade(midterm,final,homework); }
std::string name() const {return n;}
};
class Post_Grad:public Grad{
double thesis;
protected:
Post_Grad* clone() const {return new Post_Grad(*this);}
public:
Post_Grad():thesis(0) { }
Post_Grad( std::istream& is) {read(is); }
std::istream& read( std::istream&);
double grade()const {return std::min(thesis,Grad::grade());}
};
#endif
实现
#include"grad.h"
using namespace std;
istream& read_hw( istream& is, vector<double>& hw){
hw.clear();
if(is){
double x;
while(is>>x)
hw.push_back(x);
is.clear();
}
return is;
}
istream& Grad::read_common( istream& is){
is>>n>>midterm>>final;
return is;
}
istream& Grad::read( istream& is){
read_common(is);
::read_hw(is,homework);
return is;
}
istream& Post_Grad::read( istream& is){
read_common(is);
is>>thesis;
::read_hw(is,homework);
return is;
}
成绩处理头文件
#ifndef _grade_deal_h
#define _grade_deal_h
#include<stdexcept>
#include<vector>
double grade(double,double,const std::vector<double>&);
double grade(double,double,double);
#endif
成绩实现源文件
#include"grade_deal.h"
#include<algorithm>
using namespace std;
template <class T> T median( vector<T> hw){
typename vector<T>::size_type sz=hw.size();
if(sz==0)
throw domain_error("vector size false");
sort(hw.begin(),hw.end());
typename vector<T>::size_type mid=hw.size()/2;
return sz%2==0? (hw[mid-1]+hw[mid])/2 : hw[mid];
}
double grade(double midterm,double final,const vector<double>& hw){
if(hw.size()==0)
throw domain_error("vector size false");
return grade(midterm,final,median(hw));
}
double grade(double midterm,double final,double hw){
return midterm*0.2+final*0.4+0.4*hw;
}
学生成绩处理接口类头文件
#ifndef _student_h
#define _student_h
#include"grad.h"
class Student{
Grad* cp;
public:
Student(): cp(0) { }
Student( std::istream& is) {read(is);}
Student(const Student&);
Student& operator=(const Student&);
~Student() {delete cp;}
std::string name() const{
if(cp)
return cp->name();
else throw std::domain_error("uninitial student");
}
double grade()const {
if(cp)
return cp->grade();
else throw std::domain_error("uninitial student");
}
static bool compare(const Student& s1,const Student& s2){
return s1.name() < s2.name();
}
std::istream& read( std::istream& is);
};
#endif
实现
#include"student.h"
using namespace std;
istream& Student::read( istream& is){
delete cp;
char c;
is>>c;
if(c=='G')
cp=new Grad(is);
else if(c=='P')
cp=new Post_Grad(is);
return is;
}
Student::Student(const Student& stu){
if(stu.cp)
cp=stu.cp->clone();
}
Student& Student::operator=(const Student& stu){
if(&stu != this){
if(stu.cp){
delete cp;
cp=stu.cp->clone();
}else cp=0;
}
return *this;
}
测试例程
#include"student.h"
#include<ios>
#include<iomanip>
using namespace std;
int main(){
vector<Student> students;
Student record;
string::size_type maxlen=0;
while(record.read(cin)){
maxlen=max(maxlen,record.name().size());
students.push_back(record);
}
sort(students.begin(),students.end(),Student::compare);
for(vector<Student>::size_type i=0;i!=students.size();i++){
cout<<students[i].name()<<string(maxlen+1-students[i].name().size(),' ');
try{
double final_grade=students[i].grade();
streamsize prec=cout.precision();
cout<<setprecision(3)<<final_grade<<setprecision(prec)<<endl;
}catch(domain_error e){
cout<<e.what()<<endl;
}
}
return 0;
}