MI/多重继承 & 虚继承

1,没有虚继承的MI

#include <iostream>
#include <string>
using namespace std;
/*
MI(多重继承)
虚基类
*/

/*
MI继承图:
test_base
/      \
/        \
test1      test1_1
\        /
\      /
test2

*/

class test_bae   //基类 test_base
{
private:
string str;

public:
	test_bae(string str):str(str){}
	 virtual void show()
	{
		cout << this->str << " (地址:" << this << ")\n";
	}
};

class test1:public test_bae //test_base的派生类
{
private:
int a;
public:
	test1(string str, int a):test_bae(str),a(a){}
	virtual void show()
	{
		test_bae::show();
		cout << "a: " << a << endl;
	}
};

class test1_1:public test_bae //test_base的派生类
{
private:
	double b;
public:
	test1_1(string str, double b):test_bae(str),b(b){}
	virtual void show()
	{
		test_bae::show();
		cout << "b: " << b << endl;
	}
};

class test_2:public test1, public test1_1 //继承自test1和test1_1
{
public:
	test_2(string str, int a, double b):test1(str,a),test1_1(str,b){}
	virtual void show()
	{
		test1::show();
		test1_1::show();
	}
};


void main()
{
	test_2 one("hello",1,2.2);
	one.show();
	/*
	输出结果:
	hello (地址:0018FC5C)
    a: 1
    hello (地址:0018FC7C)
    b: 2.2
显然这个结果(输出两个不同地址重复的string)并不是我们想要的,问题出在哪里?
观察地址可以发现,程序运行时生成了两个基类(一个来自test1 一个来自test1_1), 所以才会有两个基类
解决办法 使用虚基类, 看下面代码
	*/

system("pause");
}

2,有虚继承没有分离show数据的MI

class test_bae   //基类 test_base
{
private:
string str;

public:
	test_bae(string str):str(str){}
	virtual void show()
	{
		cout << this->str << " (地址:" << this << ")\n";
	}
};

class test1:public virtual test_bae //test_base的派生类
{
private:
int a;
public:
	test1(string str, int a):test_bae(str),a(a){}
	virtual void show()
	{
		test_bae::show();
		cout << "a: " << a << endl;
	}
};

class test1_1: virtual public test_bae //test_base的派生类
{
private:
	double b;
public:
	test1_1(string str, double b):test_bae(str),b(b){}
	virtual void show()
	{
		test_bae::show();
		cout << "b: " << b << endl;
	}
};

class test_2:public test1, public test1_1 //继承自test1和test1_1
{
public:
	test_2(string str, int a, double b):test_bae(str),test1(str,a),test1_1(str,b){} //这里有变动,必须显示的调用所有的基类的构造函数
	virtual void show()
	{
		test1::show();
		test1_1::show();
	}
};


void main()
{
	test_2 one("hello",1,2.2);
	one.show();
	/*
	输出结果:
	hello (地址:004FF8CC)
    a: 1
    hello (地址:004FF8CC)
    b: 2.2
	显然现在两个地址一样了 证明只有一个基类了,解决办法就是虚继承
	注意:虚继承 没法传递基类构造函数 所以必须显示的调用基类函数(参见上面代码的构造函数)
	接下来还有一个问题就是基类被输出了两次,解决办法就是把 show 里面的数据分开,代码如下:
	*/

system("pause");
}
3,使用了虚继承的MI&分离了show数据

class test_bae   //基类 test_base
{
private:
	string str;

public:
	test_bae(string str):str(str){}
	virtual void show()
	{
		this->Date();
	}
protected:
	virtual void Date() const
	{
		cout << this->str << " (地址:" << this << ")\n";
	}
};

class test1:public virtual test_bae //test_base的派生类
{
private:
	int a;
public:
	test1(string str, int a):test_bae(str),a(a){}
	virtual void show()
	{
		test_bae::Date();
		this->Date();
	}
protected:
	virtual void Date() const
	{
		cout << "a: " << a << endl;
	}
};

class test1_1: virtual public test_bae //test_base的派生类
{
private:
	double b;
public:
	test1_1(string str, double b):test_bae(str),b(b){}
	virtual void show()
	{
		test_bae::Date();
		this->Date();
	}
protected:
	virtual void Date() const
	{
		cout << "b: " << b << endl;
	}
};

class test_2:public test1, public test1_1 //继承自test1和test1_1
{
public:
	test_2(string str, int a, double b):test_bae(str),test1(str,a),test1_1(str,b){} //这里有变动,必须显示的调用所有的基类的构造函数
	virtual void show()
	{
		test_bae::Date();
		test1::Date();
		test1_1::Date();
		this->Date();
	}
protected:
	virtual void Date() const
	{
	
	}
};


void main()
{
	test_2 one("hello",1,2.2);
	one.show();
	/*
	输出结果:
	hello (地址:0018F930)
    a: 1
    b: 2.2
	完美!现在是我们想要的结果,具体改动就是
	test_base 里面添加一个 保护函数 test_base::Date()
	test1 里面添加一个 保护函数 test1::Date()
	test1_1 里面添加一个 保护函数 test1_1::Date()
	Data 函数只包含本类的 要输出的数据, 然后show函数在把 各个Date 连接起来
	!!over!!
	*/
	system("pause");
}

/*
总结:
多重继承(MI) 必须使用虚继承,不然会出现多个基类;
虚继承中基类的构造函数 必须显示的调用;
考虑某些函数子类的函数与父类的函数冲重复的情况 比如前面的 show 函数,所以必须将重复去掉 分离某些数据(较好的方法用protected继承)
*/

你可能感兴趣的:(继承,MI,多重继承,虚继承,c++类继承)