C++学习笔记 第53课 被遗弃的多重继承(上)

问题引出:在C++中是否允许一个类继承自多个类?在C#和java语言中,是不能多重继承的

何为多重继承呢,简单的说,多重继承就是子类有多个父类,子类继承所有父类的成员函数与成员变量,子类对象可以当做任意父类对象使用

1.C++中的多重继承

语法规则:
在这里插入图片描述

2.编程实验-多重继承问题一

#include <iostream>

using namespace std;

class BaseA
{
   int ma;
public:
	BaseA(int a)
	{
		ma = a;
    }
	
	int GetA()
	{	
		return ma;
	}
};

class BaseB
{
   int mb;
public:
	BaseB(int b)
	{
		mb = b;
    }
	
	int GetB()
	{	
		return mb;
	}
};

class BaseC
{
	int mc;
public:
	BaseC(int c)
    {
		mc = c;;
	}
	
    int GetC()
	{
		return mc;
	}
};

class Derived:public BaseA,public BaseB,public BaseC
{
	int md;
public:
	Derived(int a,int b,int c,int d):BaseA(a),BaseB(b),BaseC(c)
	{
		md = d;
	}

	int GetD()
	{
	   return md;
	}
	
	void print()
	{
		cout << "ma = "<<GetA()<<","
				"mb = "<<GetB()<<","
				"mc = "<<GetC()<<","
				"md= "<<md<<","<<endl;
	}

};

int main()
{
    Derived d(1,2,3,4);
	cout <<"d.GetA()"<<d.GetA()<<endl;
	cout <<"d.GetB()"<<d.GetB()<<endl;
	cout <<"d.GetC()"<<d.GetC()<<endl;
	cout <<"d.GetD()"<<d.GetD()<<endl;
	   
	BaseA *pa = &d;//父类指针指向子类对象
	BaseB *pb = &d;//父类指针指向子类对象
	 
	cout <<"pa->getA()"<<pa->GetA()<<endl;
	cout <<"pb->getB()"<<pb->GetB()<<endl;
		
	void * paa = pa;
	void * pbb = pb;
	
	if(paa == pbb)
	{
		cout << "pointer is the same object"<<endl;
	}else
	{
		cout << "error"<<endl;
	}
	
	cout << "pa"<<pa<<endl;
	cout << "pb"<<pb<<endl;
	cout << "paa"<<paa<<endl;
	cout << "pbb"<<pbb<<endl;
	
	d.print();
	return 0;
}

结果:
在这里插入图片描述
从从结果看出pa与pb的地址不一样,意味着多重继承得到的对象可能拥有不同的地址,这其实是多重继承存在的一个问题,还未有解决方案
在这里插入图片描述

3.多重继承的问题二

  • 多重继承可能产生冗余的成员
    在这里插入图片描述
#include <iostream>
#include <string>

using namespace std;

class People
{
	string m_name;
	int m_age;
public:
	People(string name,int age)
	{
		m_name = name;
		m_age  = age; 
	}
	
	void print()
	{
		cout << "m_name = "<<m_name<<","
			 << "m_age  = "<<m_age <<endl;
	}
};

class Teacher : public People
{
public:
	Teacher(string name,int age):People(name,age)
	{
		
	}
	
};

class Student : public People
{
public:
	Student(string name,int age):People(name,age)
	{
		
	}
};

class Doctor : public Teacher,public Student
{
public:
	Doctor(string name,int age):Teacher(name + "1",age+1),Student(name+"2",age+2)
	{
		
	}
	
};
int main()
{
	Doctor d("Delphi",33);
	
	//d.print();会产生二义性
	d.Teacher::print();
	d.Student::print();
}

结果:
在这里插入图片描述
结果可以看出来,当多重关系出现闭合时,会产生数据冗余问题!!!那么改如何解决这个问题呢,解决方案为虚继承
在这里插入图片描述

  • 虚继承能够解决数据冗余问题
  • 中间层父类不再关系顶层父类的初始化
  • 最终子类必须直接调用顶层父类的构造函数
#include <iostream>
#include <string>

using namespace std;

class People
{
	string m_name;
	int m_age;
public:
	People(string name,int age)
	{
		m_name = name;
		m_age  = age; 
	}
	
	void print()
	{
		cout << "m_name = "<<m_name<<","
			 << "m_age  = "<<m_age <<endl;
	}
};

class Teacher : virtual public People
{
public:
	Teacher(string name,int age):People(name,age)
	{
		
	}
	
};

class Student : virtual public People
{
public:
	Student(string name,int age):People(name,age)
	{
		
	}
};

class Doctor : public Teacher,public Student
{
public:
	Doctor(string name,int age):Teacher(name + "1",age+1),Student(name+"2",age+2),People(name,age)
	{
		
	}
	
};

int main()
{
	Doctor d("Delphi",33);
	
	//d.print();会产生二义性
	//d.Teacher::print();
	//d.Student::print();
	d.print();
}

在这里插入图片描述
从结果可以看出,进行虚继承后,子类直接调用顶层父类的构造函数

问题:当架构中需要继承时,无法确定直接继承还是虚继承
解决:多继承只适合于学术,不适合实际的工程开发

4.小结

  • 只有c++支持多重继承的编程方式
  • 多重继承容易带来问题
    • 可能出现同一个对象地址不同的情况
    • 虚继承可以解决数据冗余的问题
    • 虚继承使得架构设计可能出现问题
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值