关键的点:
- 如果继承的基类又都继承于同一个基类,则将会出现二义性,即多重继承的对象包含两个最初的基类对象。
- 使用虚基类
- 从多个类(其基类相同)派生出的对象只继承一个基类对象
- 使用虚基类时构造函数,需显式地调用基类构造(仅在此合法)
- 方法上的二义性。
- 作用域解析算符
- 重新定义方法
- protected 属性
- 再继承层次结构中的类可以使用;作为协助公有接口的辅助方法
- 为什么需要用同样的基类指针或引用去指向不同的子类对象
- 暂时理解:便于用数组或其它数据结构进行管理
代码
workermi.h
#ifndef WORKERMI_H
#define WORKERMI_H
#include <iostream>
#include <string>
#include<cstdio>
using namespace std;
class Worker
{
private:
string fullname;
long id;
protected:
virtual void Data()const;//如果Data( )方法是保护的,则只能在继承层次结构中的类中使用它,在其他地方则不能使用;作为协助公有接口的辅助方法。
virtual void Get();
public:
Worker():fullname("no one"),id(0L){}
Worker(const string &s, long n):fullname(s),id(n){}
// virtual ~Worker() =0; //pure virtual function, 有它会报错
virtual void Set()=0;
virtual void Show() const = 0;
};
class Waiter: virtual public Worker
{
private:
int panache;
protected:
void Data() const;
void Get();
public:
Waiter():Worker(),panache(0){}
//派生类并不能直接访问基类 的私有数据,而必须使用基类的公有方法才能访问这些数据。
//访问的方式取决于方法。构造函数使用一种技术,而其他成员函数使用另一种技术。
//派生类构造函数在初始化基类私有数据时,采用的是成员初始化列 表语法.
//将基类信息传递给基类构造函数,然后使用构造函数体初始化BrassPlus类新增的数据项。
//非构造函数不能使用成员初始化列表语法,
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()const;
};
class Singer : virtual public Worker
{
protected:
enum {other, alto, contralto, soprano, bass, baritone, tenor};
enum {Vtypes=7};
void Data() const;
void Get();
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() const;
// ~Singer(){}
};
class SingingWaiter: public Singer,public Waiter
{
protected:
void Data() const;
void Get();
public:
SingingWaiter (){}
SingingWaiter (const string &s, long n, int p=0, int v=other):Worker(s,n),Waiter(s,n,p),Singer(s,n,v){}//why need Work(s,n)
SingingWaiter(const Worker &wk, int p=0, int v=other):Worker(wk),Waiter(wk,p),Singer(wk,v){}
SingingWaiter(const Waiter & wt, int v=other):Worker(wt),Waiter(wt),Singer(wt,v){}
SingingWaiter(const Singer &sg, int p=0):Worker(sg),Waiter(sg,p),Singer(sg){}
void Set();
void Show() const;
// ~SingingWaiter(){}
};
void test_workerMI();
#endif // WORKERMI_H
workermi.cpp
#include "workermi.h"
#include <cstring>
void Worker::Data()const
{
cout << "Name: "<<fullname<<endl;
cout <<"Employee ID"<<id<<endl;
}
void Worker::Get()
{
getline(cin,fullname);
cout<<"Enter worker's ID: ";
cin>>id;
while(cin.get() != '\n')
continue;
}
//waiter methods
void Waiter::Set()
{
cout<<"Enter waiter's full name: ";
Worker::Get();
Get();
}
void Waiter::Show() const
{
cout<< "Category: waiter\n";
Worker::Data();
Data();
}
void Waiter::Data() const
{
cout<<"Panache rating: "<<panache<<endl;
}
void Waiter::Get()
{
cout << "Enter waiter's panache rating: ";
cin>>panache;
while(cin.get()!='\n')
continue;
}
//singer methods
char *Singer::pv[Singer::Vtypes]={"other","alto","contralto","soprano","bass","baritone","tenor"};
void Singer::Set()
{
cout<<"Enter singer's name: ";
Worker::Get();
Get();
}
void Singer::Show()const
{
cout<<"category: singer \n";
Worker::Data();
Data();
}
void Singer::Get()
{
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<<"\n";
cin>>voice;
while (cin.get() != '\n')
continue;
}
void Singer::Data()const
{
cout<<"Vocal range: "<<pv[voice]<<endl;
}
//singingWaiter methods
void SingingWaiter::Data()const
{
Singer::Data();
Waiter::Data();
}
void SingingWaiter::Get()
{
Waiter::Get();
Singer::Get();
}
void SingingWaiter::Set()
{
cout <<"Enter singing waiter's name: ";
Worker::Get();
Get();
}
void SingingWaiter::Show() const
{
cout<<"category: singing waiter \n";
Worker::Data();
Data();
}
void test_workerMI()
{
const int SIZE=5;
Worker *lolas[SIZE];
int ct;
for(ct=0;ct<SIZE;ct++)
{
char choice;
cout << "Enter the employee category:\n "
<< "w: waiter s:singer "
<< "t: singer waiter q:quit\n";
cin>>choice;
while (strchr("wsqt",choice) ==NULL)
{
cout << "Please enter a w, s, t, or 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 SingingWaiter;
}
cin.get();
lolas[ct]->Set();
}
cout<<"\nHere is your staff:\n";
int i;
for(i=0;i<ct;i++)
{
cout<<endl;
lolas[i]->Show();
}
delete []lolas;
cout << "Bye.\n";
}
关注的地方