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继承)
*/
#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继承)
*/
相关文章推荐
- PostgreSQL教程(三):表的继承和分区表详解
- Lua面向对象之类和继承浅析
- 浅析Ruby中继承和消息的相关知识
- 设计引导--一个鸭子游戏引发的设计理念(多态,继承,抽象,接口,策略者模式)
- C++实现不能被继承的类实例分析
- C# 面向对象三大特性:封装、继承、多态
- PHP类的封装与继承详解
- js继承 Base类的源码解析
- Javascript 面向对象 继承
- JavaScript 继承使用分析
- Javascript面向对象编程(二) 构造函数的继承
- Javascript中的几种继承方式对比分析
- javascript面向对象之Javascript 继承
- JavaScript 对象、函数和继承
- 详述JavaScript实现继承的几种方式(推荐)
- javascript 继承学习心得总结
- 学习javascript面向对象 javascript实现继承的方式
- 关于JavaScript的面向对象和继承有利新手学习
- JavaScript 继承详解(一)
- JavaScript 继承详解(二)