第14章 代码重用

一.Student 类的设计:使用了valarray类(很啰嗦)
1.头文件:

#ifndef STUDENT_H_
#define STUDENT_H_
#include<iostream>
#include<string>
#include<valarray>
using namespace std;
class Student
{
private:
    typedef valarray<double> ArrayDb;
    string name;
    ArrayDb scores;
    ostream &arr_out(ostream &os);
public:
    Student():name("Null Student"),scores(){}
    explicit Student(const string &s):name(s),scores(){}
    explicit Student(int n):name("Nully"),scores(n){}
    Student(const string &s,int n):name(s),scores(n){}
    Student(const string &s,const ArrayDb &a):name(s),scores(a){}
    Student(const char *str,const double *pd,int n):name(str),scores(pd,n){}
    ~Student(){}                 //以上全是内联函数 实现
    double Average();
    string &Name();
    double &operator[](int i);
    double operator[](int i)const;
    friend istream &operator>>(istream &is,Student &stu);
    friend istream &getline(istream &is,Student &stu);
    friend ostream &operator<<(ostream &os, Student &stu);
};
#endif

2.类方法的实现:

#include<iostream>
#include"student.h"
using namespace std;
double Student::Average()
{
    if(scores.size()>0)
        return scores.sum()/scores.size();
    else 
        return 0;
}
 string &Student::Name()
{
    return name;
}
 double &Student::operator[](int i)
 {
     return scores[i];
 }
double Student::operator[](int i)const
{
        return scores[i];
}
ostream &Student::arr_out(ostream &os)
{
    int i;
    if(scores.size()>0)
    {
        for(i=0;i<scores.size();i++)
        {
            os<<scores[i]<<" ";
            if(i%5==4)
                os<<endl;
        }
        if(i%5!=0)
            os<<endl;
    }
    else 
        os<<"empty array";
    return os;
}
istream &operator>>(istream &is,Student &stu)
{
    is>>stu.name;
    return is;
}
istream &getline(istream &is,Student &stu)
{
    getline(is,stu.name);
    return is;
}
ostream &operator<<(ostream &os,Student &stu)
{
    os<<"Scores for"<<stu.name<<":\n";
    stu.arr_out(os);
    return os;
}

3.测试类:

#include<iostream>
#include"student.h"
using namespace std;
void set(Student &sa,int n);
const int pupils=3;
const int quizzes=5;
int main()
{
    Student ada[pupils]={Student(quizzes),Student(quizzes),Student(quizzes)};
    int i;
    for(i=0;i<pupils;++i)
        set(ada[i],quizzes);
    cout<<"\nStudent List:\n";
    for(i=0;i<pupils;++i)
      cout<<ada[i].Name()<<endl;
    cout<<"\nResults:";
    for(i=0;i<pupils;++i)
    {
        cout<<endl<<ada[i];
        cout<<"average:"<<ada[i].Average()<<endl;
    }
    cout<<"Done!\n";
    return 0;
}

void set(Student &sa,int n)
{
    cout<<"Please enter the student's name:";
    getline(cin,sa);
    cout<<"Please enter"<<n<<"quiz scores:\n";
    for(int i=0;i<n;i++)
        cin>>sa[i];
    while (cin.get()!='\n')
        continue;
}

二.私有继承(没有掌握)
三.多重继承
1.此例中一堆没用的构造函数,看起来很别扭。主要是set和show方法。在派生类中调用了基类的set和show方法,来设置和显示共有部分的数据。

#ifndef WORKER_H_
#define WORKER_H_
#include<iostream>
#include<string>
using namespace std;
class Worker
{
private:
    string fullname;
    long id;
public:
    Worker():fullname("none"),id(0L){}
    Worker(const string &s,long n):fullname(s),id(n){}
    virtual ~Worker()=0;
    virtual void Set();
    virtual void Show();
};
class Waiter:public Worker
{
private:
    int panache;
public:
    Waiter():Worker(),panache(0){}
    Waiter(const string &s,long n,int p=0):Worker(s,n),panache(p){}
    Waiter(const Worker &wk,int p=0):Worker(wk),panache(p){}  //!!!!!!!
    void Set();
    void Show();
};
class Singer:public Worker
{
protected:
    enum{other,alto,contralto,soprano,bass,baritone,tenor};
    enum{Vtypes=7};
private:
    static char *pv[Vtypes];
    int voice;
public:
    Singer():Worker(),voice(other){}
    Singer(const string &s,long n,int v=other):Worker(s,n),voice(v){}
    Singer(const Worker &wk,int v=other):Worker(wk),voice(v){}
    void Set();
    void Show();
};
#endif  WORKER_H_
#include<iostream>
#include"worker0.h"
using namespace std;
Worker::~Worker()
{}
void Worker::Set()
{
    cout<<"Enter name of Worker:";
    getline(cin,fullname);//使用getline()可以输入带有空格的字符串。
    cout<<"Enter id of Worker:";
    cin>>id;
    while(cin.get()!='\n')           //一般要与getline()同时使用。
        continue;
}
void Worker::Show()
{
    cout<<"Name:"<<fullname<<endl;
    cout<<"Id:"<<id<<endl;
}
void Waiter::Set()
{
    Worker::Set(); //派生类无法直接访问基类私有成员 可以通过调用基类的公有成员函数来访问。
    cout<<"Enter panache of waiter:";
    cin>>panache;
    while(cin.get()!='\n')
        continue;
}
void Waiter::Show()
{
    cout<<"Category waiter:\n";
    Worker::Show();
    cout<<"Panache:"<<panache<<endl;
}

char *Singer::pv[]={"other","alto","contralto","soprano","bass","baritone","tenor"};//?????????

void Singer::Set()
{
    Worker::Set();
    cout<<"Enter number for singer's vocal range:\n ";
    int i;
    for(i=0;i<Vtypes;i++)
    {
        cout<<i<<":"<<pv[i]<<"  ";
        if(i%4==3)
            cout<<endl;
    }
    if(i%4!=0)
        cout<<endl;
    cin>>voice;
    while(cin.get()!='\n')
        continue;

}
void Singer::Show()
{
    cout<<"Category:singer\n";
    Worker::Show();
    cout<<"Vocal range:"<<pv[voice]<<endl;
}
#include<iostream>
#include"worker0.h"
using namespace std;
const int N=4;
int main()
{
    Waiter Bob("Bob Apple",314L,5);
    Singer Bev("Beverly HIlls",522L,3);
    Waiter w_temp;
    Singer s_temp;
    Worker *pw[N]={&Bob,&Bev,&w_temp,&s_temp};
    int i;
    for(i=2;i<N;i++)
    {
        pw[i]->Set();
    }
    for(i=0;i<N;i++)
    {
        pw[i]->Show();
        cout<<endl;
    }
    return 0;
}

2.虚基类使得从多个类(它们的基类相同)派生出的对象只继承一个基类对象。使用关键字virtual。

#ifndef WORKERMI_H_
#define WORKERMI_H_
#include<string>
using namespace std;
class Worker
{
private:
    string fullname;
    long id;
public:
    Worker(const string &s="none",long n=0);
    virtual ~Worker()=0;
    virtual void data();//输出共有部分
    virtual void get();//输入共有部分
    virtual void set()=0;//调用data(),并输入特有部分
    virtual void show()=0;//调用get(),并输出特有部分
};
class Waiter:virtual public Worker
{
private:
    int panache;
public:

    Waiter(const string &s="none",long n=0,int p=0);
    Waiter(const Worker &wk,int p=0);
    void data();
    void get();
    void set();
    void show();
};
class Singer:virtual public Worker
{
protected:
    enum{other,alto,contralto,soprano,base,baritone,tenor};//分别为0,1,2,3,4,5,6
    enum{Vtypes=7};
private:
    static char *pv[Vtypes];
    int voice;
public:

    Singer(const string &s="none",long n=0,int v=other);
    Singer(const Worker &wk,int v=other);
    void data();
    void get();
    void set();
    void show();
};
class SingerWaiter:public Singer,public Waiter
{
public:
    //SingerWaiter();
    SingerWaiter(const string &s="none",long n=0,int p=0,int v=other);
    SingerWaiter(const Worker &wk,int p=0,int v=other);
    void data();
    void get();
    void set();
    void show();
};
#endif WORKERMI_H_
#include<iostream>
#include"workmi.h"
using namespace std;

Worker::Worker(const string &s,long n)
{
    fullname=s;
    id=n;
}
Worker::~Worker()
{}
void Worker::data()  //输出共有部分的数据
{
    cout<<"Name: "<<fullname<<endl;
    cout<<"Id:   "<<id<<endl;
}
void Worker::get()   //输入共有部分的数据
{
    //cout<<"Enter Worker's Name:";
    getline(cin,fullname);
    cout<<"Enter Worker's Id:";
    cin>>id;
    while(cin.get()!='\n')
        continue;
}

Waiter::Waiter(const string &s,long n,int p):Worker(s,n)
{
    panache=p;
}
Waiter::Waiter(const Worker &wk,int p):Worker(wk)
{
    panache=p;
}
void Waiter::set()
{
    cout<<"Enter Waiter's name:";
    Worker::get();  //输入共有部分的数据
    get();         //  输入自身特有数据
}
void Waiter::get()
{
    cout<<"Enter Waiter's panache:";
    cin>>panache;
}
void Waiter::data()
{
    cout<<"Panache:"<<panache<<endl;
}
void Waiter::show()
{
    cout<<"Category:waiter\n";
    Worker::data();
    data();
}
Singer::Singer(const string &s,long n,int v):Worker(s,n)
{
    voice=v;
}
Singer::Singer(const Worker &wk,int v):Worker(wk)
{
    voice=v;
}

char *Singer::pv[]={"other","alto","contralto","soprano","bass","baritone","tenor"};//?????????

void Singer::set()
{
    cout<<"Enter Singer's name:";
    Worker::get();  //输入共有部分的数据
    get();         //  输入自身特有数据
}
void Singer::get()
{
    cout<<"Enter Singer's number of vocal range:\n";
    int i;
    for(i=0;i<Vtypes;i++)
    {
        cout<<i<<":"<<pv[i]<<"  ";
        if(i%4==3)
            cout<<endl;
    }
    if(i%4!=0)
        cout<<endl;//输出数组 提供选择
    cin>>voice;  //输入选择第几个
}
void Singer::data()
{
    cout<<"Voice:"<<pv[voice]<<endl;
}
void Singer::show()
{
    cout<<"Category:singer\n";
    Worker::data();
    data();
}
SingerWaiter::SingerWaiter(const string &s,long n,int p,int v):Worker(s,n),Waiter(s,n,p),Singer(s,n,v)
{}
SingerWaiter::SingerWaiter(const Worker &wk,int p,int v):Worker(wk),Waiter(wk,p),Singer(wk,v)
{}
void SingerWaiter::data()
{
    //Worker::data();
    Singer::data();
    Waiter::data();
}
void SingerWaiter::get()
{
    Singer::get();
    Waiter::get();
}
void SingerWaiter::set()
{
    cout<<"Enter singerwaiter's name:";
    Worker::get();
    get();
}
void SingerWaiter::show()
{
    cout<<"Category singerwaiter:\n";
    Worker::data();
    data();
}
#include<iostream>
#include"workmi.h"
#include<cstring>
using namespace std;
const int N=2;
int main()
{
    Worker *lolas[N];
    int ct;
    for(ct=0;ct<N;ct++)
    {
        char choice;
        cout<<"Enter the employee category:\n"<<"w:waiter  s:singer  t:singerwaiter  q:quit\n";
        cin>>choice;
        while(strchr("wstq",choice)==NULL)//一定要大写才行
        {
            cout<<"Please enter a w s t q:";
            cin>>choice;
        }
        if(choice=='q')
            break;
        switch(choice)
        {
        case 'w':lolas[ct]=new Waiter;
            break;
        case 's':lolas[ct]=new Singer;
            break;
        case 't':lolas[ct]=new SingerWaiter;
            break;
        }
        cin.get();
        lolas[ct]->set();
    }
    cout<<"\nHere is your staff:\n";
    int i;
    for(i=0;i<ct;i++)
    {
        cout<<endl;
        lolas[i]->show();
    }
    for(i=0;i<ct;i++)
        delete lolas[i];
    cout<<"Bye!";
    return 0;
}

3.模板类

#ifndef STACKTP_H_
#define STACKTP_H_
template<typename Type>
class Stack
{
private:
    enum {MAX=10};
    Type items[MAX];
    int top;
public:
    Stack();
    bool isempty();
    bool isfull();
    bool push(const Type &item);
    bool pop(Type &item);
};
template <typename Type>
Stack<Type>::Stack()
{
    top=0;
}
template<typename Type>
bool Stack<Type>::isempty()
{
    return top==0;
}
template<typename Type>
bool Stack<Type>::isfull()
{
    return top==MAX;
}
template<typename Type>
bool Stack<Type>::push(const Type &item)
{
    if(top<MAX)
    {
        items[top++]=item;
        return true;
    }
    else 
        return false;
}
template<typename Type>
bool Stack<Type>::pop(Type &item)
{
    if(top>0)
    {
        item=items[--top];
        return true;
    }
    else 
        return false;
}
#endif STACKTP_H_
#include<iostream>
#include<string>
#include<cctype>
#include"stacktp.h"
using namespace std;
int main()
{
    Stack<string> st;
    char ch;
    string s;
    cout<<"Enter A to add,P to pop,Q to quit:\n";
    while(cin>>ch&&toupper(ch)!='Q')
    {
       while(cin.get()!='\n')
            continue;//消除无用的字符
        switch(ch)
        {
            case 'A':
            case 'a':
                if(st.isfull())
                    cout<<"Stack is full!\n";
                else 
                 {  cout<<"Enter a string:";
                    getline(cin,s);
                   // cin>>s;  不能输入带有空格的字符串 cin>>s 只能读取一个不带空格的字符串
                    st.push(s);
                    cout<<"push sucessfully!\n";
                }
                break;
            case 'p':
            case 'P':
                if(st.isempty())
                    cout<<"Stack is empty!\n";
                else
                {   st.pop(s);
                    cout<<"The string poped is:"<<s<<endl;
                }
                break;
        }
        cout<<"Enter A to add,P to pop,Q to quit:\n";
    }
    cout<<"Bye!\n";
    return 0;
}

4.ArrayTP<ArrayTP<int ,5>,10> twodeep;
相当于一个二维的数组 twodeep[i][j];

5.使用多个类型参数的模板类

#include<iostream>
#include<string>
using namespace std;
template<typename T1,typename T2>
class Pair
{
private:
    T1 a;
    T2 b;
public:
    Pair(const T1 &ta,const T2 &tb)
    {
        a=ta;
        b=tb;
    }
    T1 &geta()  //引用类型则是可修改的左值 可以进行修改
    {return a;}
    T2 &getb()
    {return b;}
};
int main()
{
    Pair<string,int> rating[4]=
    {
        Pair<string,int>("yan",5),  //类名为Pair<string,int>
        Pair<string,int>("wang",4),
        Pair<string,int>("su",3),
        Pair<string,int>("cao",2)
    };
    int n=sizeof(rating)/sizeof(Pair<string,int>);
    for(int i=0;i<n;i++)
    {
        cout<<rating[i].getb()<<": "<<rating[i].geta()<<endl;
    }
    rating[3].getb()=8;
    rating[3].geta()="hahha";
    cout<<rating[3].getb()<<": "<<rating[3].geta()<<endl;
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值