多继承带来的问题

首先看这个头文件

#ifndef WORKER0_H_
#define WORKER0_H_
#include<iostream>

class Worker
{
private:
	std::string fullname;
	long id;
public:
	Worker():fullname("no one"),id(0l){}
	Worker(const std::string &s,long n):fullname(s),id(n){}
	virtual ~Worker()=0;
	virtual void Set();
	virtual void Show()const;
};

class waiter:public Worker
{
private:
	int panache;
public:
	waiter():Worker(),panache(0){}
	waiter(const std::string &s,long n,int p):Worker(s,n),panache(p){}
	waiter(const Worker & w,int p):Worker(w),panache(p){}
	~waiter(){}
	void Set();
	void Show()const;
};

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

#endif
假如从Singer和Waiter中公有派生出SingingWaiter类,将会带来什么问题呢?

首先,SingingWaiter有多少个Worker组件?因为Singer和Waiter都从Worker中继承了组件,然后两者都派生出了SingingWaiter,那么这个类就会有两个Worker组件。

解决方法是使用虚基类。

虚基类使得从多个类(有共同的基类)派生出的对象只继承一个基类对象。用法如下:

class Singer:virtual public Worker{};

class Waiter:virtual public Worker{};

然后,这样就可以使用多继承了:class SingingWaiter:public Singer,public Waiter{};

现在,SingingWaiter对象只包含worker对象的一个副本。

第二个问题,关于构造函数的问题:

对于构造函数的初始化列表,折成应该是这样进行的:

SingingWaiter(CONST Worker &wk,int p=0,int v=Singer::other):Waiker(wk,p),Singer(wk,v){}

但是,这样会引起一个问题,将wk传递给Worker的时候,会经过两条路径(waiter和singer)。为避免这种冲突,C++在基类是虚的时候,禁止信息经过中间类自动传递给基类。因此,上述构造函数将初始化成员panache和voice,但wk参数中的信息将不会传递给子对象Waiter。然而编译器必须在构造派生对象前构造基类对象组件;在上述情况下,编译器将使用Worker的默认构造函数。

  如果不希望默认构造函数来构造虚基类对象,则需要显式地调用所需的基类构造函数。因此,构造函数应该是这样的:

SingingWaiter(const Worker & wk,int p=0,int v=Singer::other):Worker(wk),Waiter(wk,p),Singer(wk,v){}

上述代码将显式地调用构造函数worker

多继承还会引起函数调用的二义性。例如,SingingWaiter中没有新加的成员,所以可以不用重新定义show(),但是,在但继承中,可以直接调用最近的父类的函数,可现在是多继承,有两个父类,那么,将使用那个呢?

这事,有两种解决方法,可以使用作用于解析运算符,但是,最好还是重新定义。

但是重新定义还有个小问题:

void SingingWaiter::show()

{
Singer::Show();

Waiter::Show();

}

这样讲显式名字两次如何解决呢?

一种方法是使用模块化方式,而不是递增方式,即提供货源一个只显示Worker组件的方法和一个只显示Waiter组件或Singer组件的方法。然后再SingingWaiter方法中将组件组合起来。(就是Waiter只显示他自己的组件,然后定义一个show,提供两个方法,一个是他本是组件的显示,另一个是基类的显示)


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值