C++ pirmer笔记(二)
多继承(MI)
ps:写这些笔记只是为了记录一下自己的学习过程,上面的代码都是c++primerplus里面的,前面几个章节的内容有空会补起来
workermi.h
#pragma once
#include <string>
class Worker
{
private:
std::string fullname;
long id;
protected:
//获取Worker类的信息组件
virtual void Data()const;
//设置Worker类的信息组件
virtual void Get();
public:
Worker() :fullname("no one"), id(0l){}
Worker(const std::string& s, long n) :fullname(s), id(n){}
virtual ~Worker() = 0;
virtual void Set() = 0;
virtual void Show()const = 0;
};
class Waiter :virtual public Worker
{
private:
int panache;
protected:
//获取Waiter类的信息组件
virtual void Data()const;
//设置Waiter类的信息组件
virtual void Get();
public:
Waiter() : Worker(), panache(0){}
Waiter(const std::string& s, long n, int p = 0) : Worker(s, n), panache(p){}
Waiter(const Worker& w, int p = 0) :Worker(w), panache(p){}
void Set();
void Show()const;
};
class Singer :virtual public Worker
{
protected:
enum{other,alto,contralto,soprano,bass,baretone,tenor};
//获取Singer类的信息组件
virtual void Data()const;
//设置Singer类的信息组件
virtual void Get();
private:
const static char* pv[7];
int voice;
public:
Singer() :Worker(), voice(other){}
Singer(const std::string& s, long n, int v = other) :Worker(s, n), voice(v){}
Singer(const Worker& w, int v = other) :Worker(w), voice(v){}
void Set();
void Show()const;
};
class SingingWaiter :public Singer, public Waiter
{
protected:
//获取Waiter类的信息组件
virtual void Data()const;
//设置Waiter类的信息组件
virtual void Get();
public:
SingingWaiter(){}
SingingWaiter(const std::string& s, long n, int p = 0, int v = other)
:Worker(s,n), Singer(s,n,p), Waiter(s,n,v) {}
SingingWaiter(const Worker& w, int p = 0, int v = other)
:Worker(w), Singer(w, v), Waiter(w, p){}
SingingWaiter(const Singer& wt, int p = 0)
:Worker(wt), Singer(wt), Waiter(wt,p) {}
SingingWaiter(const Waiter& wt, int v = other)
:Worker(wt), Singer(wt, v), Waiter(wt) {}
void Set();
void Show()const;
};
workermi.cpp
#include "wokermi.h"
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
//Worker methods
Worker::~Worker(){}
//protected methods
void Worker::Data()const
{
cout << "Name: " << fullname << endl;
cout << "Id: " << id << endl;
}
void Worker::Get()
{
getline(cin, fullname);
cout << "Enter worker' id: ";
cin >> id;
while (cin.get() != '\n')
continue;
}
//Waiter methods
void Waiter::Set()
{
cout << "Enter waiter's name:";
Worker::Get();
Get();
}
void Waiter::Show()const
{
cout << "Catetory Waiter\n";
Worker::Data();
Data();
}
//protect methods
void Waiter::Data()const
{
cout << "panache rating: " << panache << endl;
}
void Waiter::Get()
{
cout << "Enter the panache rating: ";
cin >> panache;
while (cin.get() != '\n')
continue;
}
//Singert methods
const char* Singer::pv[7] = { "other","alto","contralto","soprano","bass","baretone","tenor" };
void Singer::Set()
{
cout << "Enter Singer's name: ";
Worker::Get();
Get();
}
void Singer::Show()const
{
cout << "Category Singer\n";
Worker::Data();
Data();
}
//protected methods
void Singer::Data()const
{
cout << "Vocal Range: " << pv[voice] << endl;
}
void Singer::Get()
{
cout << "Enter number for singer's vocal range:\n";
int i;
for ( i = 0; i < 7; i++)
{
cout << i << ": " << pv[i] << " ";
if (i % 4 == 3)
cout << endl;
}
if (i % 4 != 0)
cout << endl;
cin >> voice;
while (cin.get() != '\n')
continue;
}
//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();
}
use_workermi.cpp
#include <iostream>
#include <cstring>
#include "wokermi.h"
const int SIZE = 2;
int main()
{
using std::cin;
using std::cout;
using std::endl;
using std::strchr;
Worker* lolas[SIZE];
int ct;
for (ct = 0; ct < SIZE; ct++)
{
char choice;
cout << "Enter the category:\n"
<< "w: waiter, s: singer, t:singingwaiter, q: quit" << endl;
cin >> choice;
while (strchr("qswt", choice) == nullptr)
{
cout << "Enter the right word" << endl;
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;
break;
default:
cout << "wrong" << endl;
break;
}
cin.get();
lolas[ct]->Set();
}
cout << "Here is your staff" << endl;
for (int i = 0; i < SIZE; i++)
{
lolas[i]->Show();
cout << endl;
}
cout << "Bye" << endl;
return 0;
}
多继承中的问题
-
菱形继承
Singer和Waiter同时继承Worker类,SingingWaiter继承Singer和Waiter,这样一个SingingWaiter类中会有两个Worker对象.
解决办法:虚继承
-
哪个方法
多重继承中,Singer和Waiter会有相同的函数名,这时SingingWaiter调用时会出现二义性
解决办法:加上作用域
-
虚继承中新的构造函数规则
旧规则:派生类只能负责自己基类的初始化,不能负责间接基类的初始化
但是在下面的继承中,A基类的初始化不能在B和C的构造函数中进行,要在D中进行,否则将不会修改A的值
#include <iostream> using namespace std; class A { public: A() { m_a = 0; } A(int a) : m_a(a) {} int m_a; }; class B :virtual public A { public: B() {} B(int a,int b) : A(a), m_b(b) {} int m_b; }; class C :virtual public A { public: C() {} C(int a,int c) :A(a), m_c(c) {} int m_c; }; class D : public B, public C { public: D() {} // D(int a, int b, int c, int d) :m_d(d), B(a,b), C(a,c) {}这样不会对A进行初始化,相当于A的默认构造 D(int a, int b, int c, int d) : A(a),m_d(d), B(a,b), C(a,c) {} int m_d; }; int main() { D dd(5, 1, 2, 3); cout << dd.m_a << endl; return 0; }

被折叠的 条评论
为什么被折叠?



