c++中的多继承

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

多继承中的问题

  1. 菱形继承

    ​ Singer和Waiter同时继承Worker类,SingingWaiter继承Singer和Waiter,这样一个SingingWaiter类中会有两个Worker对象.

    解决办法:虚继承

  2. 哪个方法

    多重继承中,Singer和Waiter会有相同的函数名,这时SingingWaiter调用时会出现二义性

    解决办法:加上作用域

  3. 虚继承中新的构造函数规则

    旧规则:派生类只能负责自己基类的初始化,不能负责间接基类的初始化

    但是在下面的继承中,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;
    }
    
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值