您的位置:首页 > 编程语言 > C语言/C++

MI/多重继承 & 虚继承

2016-04-06 14:13 417 查看
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继承)

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息