Accelerated C++ 14 Managing memory automatically

template specialization

when we pass clone a Vec<char> grument, the compiler will use this specialized version of clone. When we pass other types of pointers, it wil instantiate the general template form of clone.

template <typename T> T* clone (const T* tp) {
    return tp->clone();
}

// the key to making Ptr< Vec<char> > work
tempalet<>
Vec<char>* clone(const Vec<char>* vp) {
    return new Vec<char> (*vp);
}

Core.h

#ifndef GUARD_core_h
#define GUARD_core_h

// Core.h

#include <string>
#include <iostream>
#include <vector>

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;

        virtual Core* clone() const { return new Core(*this); }

    protected:
        // accessible to derived classes


        std::istream& read_common(std::istream&);
        double midterm,final;
        std::vector<double> homework;

    private:
        // accessible only to Core
        std::string n;
};

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

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

//bool compare(const Core&, const Core&);

#endif

Core.cpp

// source file Core-related

#include "Core.h"
#include "/home/rhk/workspace/4_grade/median.h"

using std::string;  using std::vector;
using std::istream;

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

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

istream& Core::read_common(istream& in) {

    // read and store the student's name and exam grades
    in >> n >> midterm >> final;
    return in;
}

istream& Core::read(istream& in) {

    read_common(in);
    read_hw(in, homework);
    return in;
}

double grade(double midterm, double final, vector<double> homework) {
    return 0.2 * midterm + 0.4 * final + 0.4 * median(homework);
}

// read homworks
istream& read_hw(istream& in, vector<double>& hw) {
    if (in) {

        // get rid of previous contents
        hw.clear();

        // read homework grades
        double x;
        while (in >> x)
            hw.push_back(x);

        // clear the stream so that input will work for the next student
        in.clear();
    }
    return in;
}

bool compare(const Core& c1, const Core& c2) {
    return c1.name() < c2.name();
}

Grad.h

#ifndef GUARD_grad_h
#define GUARD_grad_h

#include "Core.h"

class Grad:public Core {
    public:
        Grad(): thesis(0) { }
        Grad(std::istream& is) { read(is); }
        double grade() const;
        std::istream& read(std::istream&);
    protected:
        Grad* clone() const { return new Grad(*this); }
    private:
        double thesis;
};


#endif

Grad.cpp

#ifndef GUARD_grad_h
#define GUARD_grad_h

#include "Core.h"

class Grad:public Core {
    public:
        Grad(): thesis(0) { }
        Grad(std::istream& is) { read(is); }
        double grade() const;
        std::istream& read(std::istream&);
    protected:
        Grad* clone() const { return new Grad(*this); }
    private:
        double thesis;
};

#endif

Handle.h

#ifndef GUARD_handle_h
#define GUARD_handle_h
#include <stdexcept>

template <class T> class Handle {
    public:
        Handle():p(0) { }
        Handle(const Handle& s): p(0) { if (s.p) p = s.p->clone(); }
        Handle& operator=(const Handle&);
        ~Handle() { delete p; }

        Handle(T* t): p(t) { }

        operator bool() const { return p; }
        T& operator*() const;
        T* operator->() const;

    private:
        T* p;
};

template <typename T>
Handle<T>& Handle<T>::operator=(const Handle& rhs) {
    if (&rhs != this) {
        delete p;
        p = rhs.p ? rhs.p->clone() : 0;
    }
    return *this;
}

template <typename T>
T& Handle<T>::operator*() const {
    if (p) return *p;
    throw std::runtime_error("unbound Handle");
}

template <typename T>
T* Handle<T>::operator->() const {
    if (p) return p;
    throw std::runtime_error("unbound Handle");
}

#endif

Student_info.h

#ifndef GUARD_Student_h
#define GUARD_Student_h
// Student_info.h
#include <iostream>
#include <stdexcept>
#include "Handle.h"
#include "Core.h"
#include "Grad.h"

class Student_info {
    public:
        Student_info() { };
        Student_info(std::istream& is) { read(is); }

        std::istream& read(std::istream&);
        std::string name() const {
            if (cp) return cp->name();
            throw std::runtime_error("uninitialized Student");
        }

        double grade() const {
            if (cp) return cp->grade();
            throw std::runtime_error("uninitialized Student");
        }

        static bool compare(const Student_info& s1, const Student_info& s2) {
            return s1.name() < s2.name();
        }

    private:
    //  Handle<Core> cp;
    Core* cp;
};

std::istream& Student_info::read(std::istream& is) {
    char ch;
    is >> ch;

    if (ch == 'U') 
        cp = new Core(is);
    else 
        cp = new Grad(is);

    return is;
};

#endif

main.cpp

#include "Core.h"
#include "Student_info.h"
#include "Grad.h"
#include <algorithm>
#include <ios>
#include <iomanip>
#include <stdexcept>

using std::string;  using std::cout;    using std::cin;
using std::endl; using std::vector; using std::max;
using std::streamsize;  using std::sort;    using std::setprecision;    
using std::domain_error;
int main() {
    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);

    for (vector<Grad>::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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值