文章目录

1 编译运行本章例子

1.1 有类型依赖

头文件:

//
// Created by MacBook Pro on 2020-03-19.
//

#ifndef ACM_TEST_H
#define ACM_TEST_H

class Core{
public:
Core():midterm(0),final(0){}
Core(std::istream& is){read(is);}

std::string name() const;

virtual std::istream& read(std::istream&);
virtual double grade() const;

protected:
std::istream& read_common(std::istream&);
double midterm, final;
std::vector<double> homework;
private:
std::string n;
};


class Grad:public Core{
public:
Grad():thesis(0){}
Grad(std::istream& is){read(is);}

double grade() const;
std::istream& read(std::istream&);
private:
double thesis;
};


std::istream& read_hw(std::istream&, std::vector<double>&);

double grade(double, double, double);
double grade(double, double, const std::vector<double>&);

double median(std::vector<double> );

bool compare(const Core& , const Core& );
bool compare_core_ptrs(const Core*, const Core*);
bool compare_grades(const Core& , const Core&);

#endif //ACM_TEST_H

源文件:

#include 
#include
#include
#include
#include
#include
#include
#include "test.h"

using std::cin; using std::cout;
using std::endl;
using std::istream;
using std::domain_error;
using std::vector;
using std::min;
using std::string;
using std::max;
using std::streamsize;
using std::setprecision;
using std::sort;
using std::string;

std::istream& read_hw(std::istream&, std::vector<double>&);

std::string Core::name() const { return n;}


istream& Core::read_common(istream& in){
in >> n >> midterm >> final;
return in;
}

istream& Core::read(istream& in){
read_common(in);
read_hw(in, homework);
return in;
}

istream& Grad::read(istream& in){
read_common(in);
in >> thesis;
read_hw(in, homework);
return in;
}

//不能将重载函数命名为模版参数,不然编译器无法决定调用按一个版本

bool compare(const Core& c1, const Core& c2){
return c1.name() < c2.name();
}
bool compare_grades(const Core& c1, const Core& c2){
return c1.grade() < c2.grade();
}
//改版一
bool compare_core_ptrs(const Core* cp1, const Core* cp2){
return compare(*cp1, *cp2);
}

double Core::grade() const{
return ::grade(midterm, final, homework);
}


double Grad::grade() const {
return min(Core::grade(), thesis);//显示表明
}

double median(vector<double> vec){
typedef vector<double>::size_type vec_sz;
vec_sz size = vec.size();
if(size == 0){
throw domain_error("median of an empty vector");
}

sort(vec.begin(), vec.end());

vec_sz mid = size/2;

return size % 2 == 0 ? (vec[mid] + vec[mid -1]) /2 : vec[mid];
}

double grade(double midterm, double final, const vector<double>& hw){
if(hw.size() == 0)
throw domain_error("student has done no homework");
return grade(midterm, final, median(hw));//如果家庭作业非空,则调用grade3
}//grade2

double grade(double midterm, double final, double hw){
return midterm * 0.2 + final * 0.4 + hw * 0.4;
}


istream& read_hw(istream& in, vector<double>& hw){
if(in){
hw.clear();
double x;
while(in >> x){
hw.push_back(x);
}
in.clear();
}
return in;
}

int main(int argc, char** argv){

//类型依赖(向量的定义)
vector<Core> students;
// vector students;

Core record;
// Grad 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(), compare);

for (vector<Core>::size_type i = 0; i != students.size(); ++i) {
cout << students[i].name()
<< string(maxlen + 1 - students[i].name().size(),' ');
try{
//grade函数(类型依赖)
double final_grade = students[i].grade();
streamsize pre = cout.precision();
cout << setprecision(3) << final_grade//Core函数
<< setprecision(pre) << endl;
}catch(domain_error e){
cout << e.what() << endl;
}
}

// for (vector::size_type i = 0; i != students.size(); ++i) {
// cout << students[i].name()
// << string(maxlen + 1 - students[i].name().size(),' ');
// try{
// //grade函数(类型依赖)
// double final_grade = students[i].grade();
// streamsize pre = cout.precision();
// cout << setprecision(3) << final_grade//Grad::grade
// << setprecision(pre) << endl;
// }catch(domain_error e){
// cout << e.what() << endl;
// }
// }
return 0;
}

1.2 摆脱类型依赖

头文件:同前
源文件:

#include 
#include
#include
#include
#include
#include
#include
#include "test.h"

using std::cin; using std::cout;
using std::endl;
using std::istream;
using std::domain_error;
using std::vector;
using std::min;
using std::string;
using std::max;
using std::streamsize;
using std::setprecision;
using std::sort;
using std::string;

std::istream& read_hw(std::istream&, std::vector<double>&);

std::string Core::name() const { return n;}


istream& Core::read_common(istream& in){
in >> n >> midterm >> final;
return in;
}

istream& Core::read(istream& in){
read_common(in);
read_hw(in, homework);
return in;
}

istream& Grad::read(istream& in){
read_common(in);
in >> thesis;
read_hw(in, homework);
return in;
}

//不能将重载函数命名为模版参数,不然编译器无法决定调用按一个版本

bool compare(const Core& c1, const Core& c2){
return c1.name() < c2.name();
}
bool compare_grades(const Core& c1, const Core& c2){
return c1.grade() < c2.grade();
}
//改版一
bool compare_core_ptrs(const Core* cp1, const Core* cp2){
return compare(*cp1, *cp2);
}

double Core::grade() const{
return ::grade(midterm, final, homework);
}


double Grad::grade() const {
return min(Core::grade(), thesis);//显示表明
}

double median(vector<double> vec){
typedef vector<double>::size_type vec_sz;
vec_sz size = vec.size();
if(size == 0){
throw domain_error("median of an empty vector");
}

sort(vec.begin(), vec.end());

vec_sz mid = size/2;

return size % 2 == 0 ? (vec[mid] + vec[mid -1]) /2 : vec[mid];
}

double grade(double midterm, double final, const vector<double>& hw){
if(hw.size() == 0)
throw domain_error("student has done no homework");
return grade(midterm, final, median(hw));//如果家庭作业非空,则调用grade3
}//grade2

double grade(double midterm, double final, double hw){
return midterm * 0.2 + final * 0.4 + hw * 0.4;
}


istream& read_hw(istream& in, vector<double>& hw){
if(in){
hw.clear();
double x;
while(in >> x){
hw.push_back(x);
}
in.clear();
}
return in;
}

int main(int argc, char** argv){
vector<Core*> students;
Core* record;

string::size_type maxlen = 0;

char ch;
while(cin >> ch){
if(ch == 'U'){
record = new Core;//为一个Core类型对象分配内存
}else{
record = new Grad;//为一个Grad类型对象分配内存
}
record->read(cin);//虚拟调用
maxlen = max(maxlen, record->name().size());//间接引用
students.push_back(record);
}

sort(students.begin(), students.end(), compare_core_ptrs);

for (vector<Core*>::size_type i = 0; i != students.size(); ++i) {
cout << students[i]->name()
<< string(maxlen + 1 - students[i]->name().size(),' ');
try{
//grade函数(类型依赖)
double final_grade = students[i]->grade();
streamsize pre = cout.precision();
cout << setprecision(3) << final_grade
<< setprecision(pre) << endl;
}catch(domain_error e){
cout << e.what() << endl;
}
delete students[i];//释放在读内存时生成的临时变量
}
return 0;
}

1.3 使用句柄类

头文件:

//
// tudent_info.h
//

#ifndef ACM_Student_info
#define ACM_Student_info

#include
#include
#include
//#include "Handle.h"

class Core{
friend class Student_info;
public:
//虚拟析构函数
//Grad在内的全部派生类会继承这个析构函数
virtual ~Core(){}

//构造函数
//默认构造函数(构造初始化器)
Core():midterm(0), final(0){}
//使用一个istream类型变量构造一个Core对象
Core(std::istream& is) {read(is);}

//存取器函数(允许对一部分数据结构访问)
std::string name() const;

virtual std::istream& read(std::istream&);

//虚拟函数(指针或引用指向的对象的实际类型在运行时是可以变化的)
//只能在类内定义
//只有以引用或指针为参数调用虚拟函数时,它们的选择才会有意义(动态绑定)
//以对象(区别于指针或引用)调用虚拟函数,在编译时候对象的类型就确定了,运行时也不会改变(静态绑定)
//通过虚拟函数+动态绑定的特性以支持多态性(多态的调用)
//多态性:一种类型可以表示几种类型(由该类派生出来的任何一个子类)
//可以用一个Core类型的指针指向一个Core类型对象或它的派生类如(Grad类型对象)
virtual double grade() const;

void regrade(double d){final = d;}
virtual void regrade(double d, double = 0){final = d;}

protected://赋予派生类访问基类中保护成员的权利
virtual Core* clone() const{return new Core(*this);}

std::istream& read_common(std::istream&);

double midterm, final;
std::vector<double> homework;
private://只有Core类成员以及它的友元函数可以访问
std::string n;
};

//继承:Grad类是从Core类中派生出来,
//Core类中的每个成员(除构造函数、赋值运算符和西沟函数除外)也是Grad的成员
class Grad:public Core{
public:
//构造函数
//两个构造函数均隐式地调用Core::Core()函数,以初始化对象中的基类部分
Grad():thesis(0){}
Grad(std::istream& is){ read(is); }

double grade() const;
std::istream& read(std::istream&);

void regrade(double d1, double d2){final = d1; thesis = d2;}
protected:
Grad* clone(){ return new Grad(*this);}
private:
double thesis;
};


std::istream& read_hw(std::istream&, std::vector<double>&);

double grade(double, double, double);
double grade(double, double, const std::vector<double>&);

double median(std::vector<double> );

bool compare(const Core& , const Core& );
bool compare_core_ptrs(const Core*, const Core*);
bool compare_grades(const Core& , const Core&);

#endif
//
// Created by MacBook Pro on 2020-03-18.
//

#ifndef ACM_HANDLE_H
#define ACM_HANDLE_H

#include
#include "Student_info.h"


class Student_info{
public:
//构造函数
Student_info ():cp(0){}
Student_info (std::istream& is):cp(0){read(is);}
//复制构造
Student_info (const Student_info&);
//赋值构造
Student_info& operator=(const Student_info&);
//析构函数
~Student_info(){delete cp;}

std::istream& read(std::istream&);

std::string name()const{
if(cp) return cp->name();
else throw std::runtime_error("uninitialized Student");
}
double grade() const {
if(cp) return cp->grade();
else throw std::runtime_error("uninitialized Student");
}
static bool compare(const Student_info& s1, const Student_info s2){
return s1.name() < s2.name();
}

void regrade(double d1, double d2 = 0){//修改成绩
if(cp) return cp->regrade(d1, d2);
else throw std::runtime_error("uninitialized Student");
}
private:
Core* cp;
};

std::istream& Student_info::read(std::istream& is){
delete cp;//如果有的话,删除所指对象,删除一个零指针也是无害的

char ch;
is >> ch;
if(ch == 'U') cp = new Core(is);
else cp = new Grad(is);
return is;
}

Student_info::Student_info(const Student_info& s):cp(0) {
if(s.cp) cp = s.cp->clone();
}

Student_info& Student_info::operator=(const Student_info& s) {
if(&s != this){
delete(cp);
if(s.cp){
cp = s.cp->clone();
}else{
cp = 0;
}
}
return *this;
}

#endif //ACM_HANDLE_H

源文件:

#include 
#include
#include
#include
#include
#include
#include
#include "Student_info.h"
#include "Handle.h"

using std::cin; using std::cout;
using std::endl;
using std::istream;
using std::domain_error;
using std::vector;
using std::min;
using std::string;
using std::max;
using std::streamsize;
using std::setprecision;
using std::sort;
using std::string;

std::string Core::name() const { return n;}

istream& Core::read_common(istream& in){
in >> n >> midterm >> final;
return in;
}

istream& Core::read(istream& in){
read_common(in);
read_hw(in, homework);
return in;
}

istream& Grad::read(istream& in){
read_common(in);
in >> thesis;
read_hw(in, homework);
return in;
}

//不能将重载函数命名为模版参数,不然编译器无法决定调用按一个版本
//指向Core类型的指针,也可以将指向Grad的指针传给它,编译器会转换为Core*
bool compare(const Core& c1, const Core& c2){
return c1.name() < c2.name();
}

bool compare_core_ptrs(const Core* cp1, const Core* cp2){
return compare(*cp1, *cp2);
}

bool compare_grades(const Core& c1, const Core& c2){
return c1.grade() < c2.grade();
}

double Core::grade() const{
return ::grade(midterm, final, homework);
}

double Grad::grade() const {
return min(Core::grade(), thesis);//显示表明
}

double median(vector<double> vec){
typedef vector<double>::size_type vec_sz;
vec_sz size = vec.size();
if(size == 0){
throw domain_error("median of an empty vector");
}

sort(vec.begin(), vec.end());

vec_sz mid = size/2;

return size % 2 == 0 ? (vec[mid] + vec[mid -1]) /2 : vec[mid];
}

double grade(double midterm, double final, const vector<double>& hw){
if(hw.size() == 0)
throw domain_error("student has done no homework");
return grade(midterm, final, median(hw));//如果家庭作业非空,则调用grade3
}//grade2

double grade(double midterm, double final, double hw){
return midterm * 0.2 + final * 0.4 + hw * 0.4;
}

istream& read_hw(istream& in, vector<double>& hw){
if(in){
hw.clear();
double x;
while(in >> x){
hw.push_back(x);
}
in.clear();
}
return in;
}

int main(int argc, char** argv){
vector<Student_info> students;
Student_info 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_info::compare);

// students[0].regrade(100,100);

for (vector<Student_info>::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;
}
/*
U jiangxuehan 87 67 89 67 89
S Nike 67 56 70 78 98 78
U Amer 87 94 56 78 56
s end s
*/

2 在Core和Grad类的构造函数中加入输出函数,使构造函数在执行的时候输出构造函数与参数列表。

仅头文件做修改

//
// Created by MacBook Pro on 2020-03-18.
//

#ifndef ACM_HANDLE_H
#define ACM_HANDLE_H

#include
#include "Student_info.h"


class Student_info{
public:
//构造函数
Student_info ():cp(0){}
Student_info (std::istream& is):cp(0){read(is);}
//复制构造
Student_info (const Student_info&);
//赋值构造
Student_info& operator=(const Student_info&);
//析构函数
~Student_info(){delete cp;}

std::istream& read(std::istream&);

std::string name()const{
if(cp) return cp->name();
else throw std::runtime_error("uninitialized Student");
}
double grade() const {
if(cp) return cp->grade();
else throw std::runtime_error("uninitialized Student");
}
static bool compare(const Student_info& s1, const Student_info s2){
return s1.name() < s2.name();
}

void regrade(double d1, double d2 = 0){
if(cp) return cp->regrade(d1, d2);
else throw std::runtime_error("uninitialized Student");
}
private:
Core* cp;
};

std::istream& Student_info::read(std::istream& is){
delete cp;//如果有的话,删除所指对象,删除一个零指针也是无害的

char ch;
is >> ch;
if(ch == 'U') cp = new Core(is);
else cp = new Grad(is);
return is;
}

Student_info::Student_info(const Student_info& s):cp(0) {
if(s.cp) cp = s.cp->clone();
}

Student_info& Student_info::operator=(const Student_info& s) {
if(&s != this){
delete(cp);
if(s.cp){
cp = s.cp->clone();
}else{
cp = 0;
}
}
return *this;
}

#endif //ACM_HANDLE_H

测试程序:

//....同上一个源文件
int main{
Core core1;
Grad grad1;

cout << "Enter Core student info:" << endl;
Core core2(cin);

cout << "Enter Grad student info:" << endl;
Grad grad2(cin);

return 0;
}

2 指出下面各条语句实际会调用哪个函数?并在name函数与grade函数中加入输出语句,输出信息表明调用了哪个函数。

测试语句:

Core* p1 = new Core;//Core::Core()
Core* p2 = new Grad;//Core::Core(),Grad()::Grad()
Core s1;//Core::Core()
Grad s2;//Core::Core,Grad()::Grad()

p1->grade();//Core::grade()
p1->name();//Core::name()

p2->grade();//Grad::grade(),Core::grade()
p2->name();//Core::name()

s1.grade();//Core::grade()
s1.name();//Core::name()

s2.name();//Grad::name()
s2.grade();//Grad::grade(),Core::grade()

头文件 同前一问
源文件:

#include 
#include
#include
#include
#include
#include
#include
#include "Student_info.h"
#include "Handle.h"

using std::cin; using std::cout;
using std::endl;
using std::istream;
using std::domain_error;
using std::vector;
using std::min;
using std::string;
using std::max;
using std::streamsize;
using std::setprecision;
using std::sort;
using std::string;

std::string Core::name() const {
#if ANNOTATE == 1
std::cerr<<" Core::name() "<<std::endl;
#endif
return n;}

istream& Core::read_common(istream& in){
in >> n >> midterm >> final;
return in;
}

istream& Core::read(istream& in){
read_common(in);
read_hw(in, homework);
return in;
}

istream& Grad::read(istream& in){
read_common(in);
in >> thesis;
read_hw(in, homework);
return in;
}

//不能将重载函数命名为模版参数,不然编译器无法决定调用按一个版本
//指向Core类型的指针,也可以将指向Grad的指针传给它,编译器会转换为Core*
bool compare(const Core& c1, const Core& c2){
return c1.name() < c2.name();
}

bool compare_core_ptrs(const Core* cp1, const Core* cp2){
return compare(*cp1, *cp2);
}

bool compare_grades(const Core& c1, const Core& c2){
return c1.grade() < c2.grade();
}

double Core::grade() const{
#if ANNOTATE == 1
std::cerr<<" Core::grade()"<<std::endl;
#endif
return ::grade(midterm, final, homework);
}

double Grad::grade() const {
#if ANNOTATE == 1
std::cerr<<" Grad::grade()"<<std::endl;
#endif
return min(Core::grade(), thesis);//显示表明
}

double median(vector<double> vec){
typedef vector<double>::size_type vec_sz;
vec_sz size = vec.size();
if(size == 0){
throw domain_error("median of an empty vector");
}

sort(vec.begin(), vec.end());

vec_sz mid = size/2;

return size % 2 == 0 ? (vec[mid] + vec[mid -1]) /2 : vec[mid];
}

double grade(double midterm, double final, const vector<double>& hw){
if(hw.size() == 0)
throw domain_error("student has done no homework");
return grade(midterm, final, median(hw));//如果家庭作业非空,则调用grade3
}//grade2

double grade(double midterm, double final, double hw){
return midterm * 0.2 + final * 0.4 + hw * 0.4;
}

istream& read_hw(istream& in, vector<double>& hw){
if(in){
hw.clear();
double x;
while(in >> x){
hw.push_back(x);
}
in.clear();
}
return in;
}

int main(int argc, char** argv){





Core* p1 = new Core;
p1->read(cin);
p1->grade();
p1->name();
delete p1;

Core* p2 = new Grad;
p2->read(cin);
p2->grade();
p2->name();
delete p2;

Core s1;
s1.read(cin);
s1.grade();
s1.name();

Grad s2;
s2.read(cin);
s2.name();
s2.grade();

return 0;
}

3 在本章类的继承树中加入一个成员函数valid,用于检测该对象是够存储一个学生的记录

在上一问的基础上:

在Core类中公有成员中加入:

bool valid() const{ return ! homework.empty();}//检查对象是否为空

Stundet_info类的公有成员中加入:

bool valid(){
if(cp) return cp->valid();
else throw std::runtime_error("uninitialized Student");
}

在Students_info句柄类公有成员中加入:

bool valid() const{
if(cp) return cp->valid();
else throw std::runtime_error("uninitialized Student");
}

把源文件中main里的:

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;
}

改为:

//修改
if(students[i].valid() == true){
double final_grade = students[i].grade();
streamsize prec = cout.precision();
cout << setprecision(3) << final_grade
<< setprecision(prec) << endl;
}else{
cout << "homework is empty!"<< endl;
}

测试程序:
在源文件的main函数中加入:

Grad grad(cin);

if (grad.valid())
cout << "Grade: " << grad.grade() << endl;
else
cout << "Empty!"<<endl;

4 在这些类中添加一个新函数,将一个分数成绩转换为相应的字母成绩

在Core的公有成员中加入:

std::string letter_grade() const;

在Students_info句柄类公有成员中加入:

std::string letter_grade() const{
if(cp) return cp->letter_grade();
else throw std::runtime_error("uninitialized Student");
}

在源文件中定义实现:

string Core::letter_grade() const {
static const double numbers[]={
97, 94, 90, 87, 84, 80, 77, 74, 70, 60, 0
};
static const char* const letters[]={
"A+","A","A-","B+","B","B-","C+","C","C-","D","F"
};
//计算成绩的个数
static const size_t ngrades = sizeof(numbers)/sizeof(*numbers);

double result = grade();
for (size_t i = 0; i < ngrades; ++i) {
if(result >= numbers[i]){
return letters[i];
}
}
return "? \? \?";
}

测试程序:
在源文件的main函数中加入:

//    cout << "Enter a Core student: " << endl;
// Core core(cin);
// cout << "Grade: " << core.letter_grade() << endl;

cout << "Enter a Grad student: " << endl;
Grad grad(cin);
cout << "Grade: " << grad.letter_grade() << endl;

5 写一个判断语句以判断某个特定的学生

在Core类公有成员中加入:

//检测是否完成了作业
virtual bool requirements_met() const{
return std::find(homework.begin(),homework.end(),0) == homework.end();
}

在Grad类的公有成员中加入:

//检查有没有写出一篇论文
bool requirements_met() const{
return Core::requirements_met() && (thesis != 0);
}

在Students_info句柄类公有成员中加入:

bool requirements_met() const{
if(cp) return cp->requirements_met();
else throw std::runtime_error("uninitialized Student");
}

测试程序:
在源文件的main中加入:

//    cout << "Enter a Core student: " << endl;
// Core core(cin);
// cout << "Requirements met? " << core.requirements_met() << endl;

cout << "Enter a Grad student: " << endl;
Grad grad(cin);
cout << "Requirements met? " << grad.requirements_met() << endl;

6 为系统添加一个新类,用于代表那些选择去通过/不及格这样的影星学分的学生。如果学生做了作业,按照正常共公式计算;如果没有做家庭作业,就只通过他们的其中与期末考试成绩计算平均分数以得到最后成绩。最后60分及其以上才算通过。

新建的类:

class Credit: public Core{
public:
Credit():Core(){}
Credit(std::istream& is):Core(is){}

double grade() const;
bool passed ()const{ return grade() >= 60; }
protected:
Credit* clone() const { return new Credit(*this);}
};

类成员函数实现:

double Credit::grade() const {
if(homework.empty()){
return (midterm + final)/2;
}else{
return Core::grade();
}
}

测试程序:

int main(int argc, char** argv){
cout << "Enter a Credit student: " << endl;
Credit credit(cin);
cout << "Grade: " << credit.grade() << endl;
cout << "Passed? " << credit.passed() << endl;

return 0;
}

7 为系统添加一个类,该类用于表示查分的学生

新增加的类:

class Audit:public Grad{
public:
typedef std::map<std::string, double> mp;
typedef std::map<std::string, double>::const_iterator const_iterator;
typedef std::map<std::string, double>::iterator iterator;

Audit(){}
Audit(std::istream& is){ read(is);}

std::istream& read(std::istream&);

void print_checked(const std::string& name)const{

if(checked(name) != -1){
std::cout <<checked(name) << std::endl;
}else{
std::cout << "Without this student!"<<std::endl;
}
}

protected:
Audit* clone() const{ return new Audit(*this);}
double checked(const std::string&) const;
private:
mp students_garde;
};

成员函数实现:

istream& Audit::read(std::istream &is) {
Core* record;

char ch;

while(is >> ch) {
if (ch == 'U') {
record = new Core;//为一个Core类型对象分配内存
} else{
record = new Grad;//为一个Grad类型对象分配内存
}
record->read(is);//虚拟调用
students_garde[record->name()] = record->grade();
}

return is;
}

double Audit::checked(const std::string & name) const{
const_iterator iter = students_garde.find(name);
if(iter != students_garde.end()){
return iter->second;
}else{
return -1;
}
}

在Core类中增加友元:

friend class Audit;

测试程序:

int main(int argc, char** argv){
//读入数据
std::ifstream infile("/Users/macbookpro/CLionProjects/ACM/students10.txt");

Audit audit(infile);
infile.close();
infile.clear();
//查询
string name;
while(cin >> name){
audit.print_checked(name);
}
return 0;
}

测试数据:

U Geert 90 80 90 65 70 90
G Pieter 81 92 90 40 50 60 70
U Lotte 60 80 90 45 60 70
G Jan 30 20 80 40 50 30 40
G Joris 72 76 60 70 60 70 60
U Mike 78 80 90 65 70 80
G LiMing 40 50 30 62 55 59 60
U James 89 80 90 95 88 87
G Kobe 89 78 65 98 87 83 83
G Oboma 97 99 92 89 93 91 90

8 写一个程序生成一个成绩报表,可以处理前面的全部4种类的对象。

继续完善Audit类:

class Audit:public Core{
public:
typedef std::map<std::string, double> mp;
typedef std::map<std::string, double>::const_iterator const_iterator;
typedef std::map<std::string, double>::iterator iterator;

Audit():maxlen(0){}
Audit(std::istream& is){ read(is);}

std::istream& read(std::istream&);

void print_checked(const std::string& name) const{

if(checked(name) != -1){
std::cout <<checked(name) << std::endl;
}else{
std::cout << "Without this student!"<<std::endl;
}
}

void print_chart() const{
if(students_garde.size() != 0){
for (const_iterator iter = students_garde.begin(); iter != students_garde.end(); ++iter) {
std::cout<< iter->first << std::string(maxlen + 1 - iter->first.size(),' ')
<< std::string(iter->second/5, '=') << std::endl;

}
}
}
protected:
Audit* clone() const{ return new Audit(*this);}
double checked(const std::string&) const;
private:
mp students_garde;
std::string::size_type maxlen;
};

成员函数实现:

istream& Audit::read(std::istream &is) {
Core* record;

char ch;
maxlen = 0;

while(is >> ch) {
if (ch == 'U') {
record = new Core;//为一个Core类型对象分配内存
} else{
record = new Grad;//为一个Grad类型对象分配内存
}
record->read(is);//虚拟调用
maxlen = max(maxlen, record->name().size());
students_garde[record->name()] = record->grade();
}

return is;
}

double Audit::checked(const std::string & name) const {
const_iterator iter = students_garde.find(name);
if(iter != students_garde.end()){
return iter->second;
}else{
return -1;
}
}

测试程序:

int main(int argc, char** argv){
//读入数据
std::ifstream infile("/Users/macbookpro/CLionProjects/ACM/students10.txt");

Audit audit(infile);
infile.close();
infile.clear();
//查询
audit.print_chart();

return 0;
}

数据同前一问:
测试结果展示:
第十三章习题 继承和动态绑定的使用_#include

9 如果13.4.2节中定义的赋值操作如果不能判断一个复制操作是否自我赋值会导致什么结果?

如果不检测的话,就会先把要左操作数删除并释放对象内存呢,但是右操作数和左操作数指向同一对象,那么右操作数也会被同时删除并释放空间。这是用右操作数复制非左操作数,但是右操作数已经为空,会被赋予不可预知的值。