多重继承
多重继承是指一个派生类可以有多个基类,class 类名: 继承方式 基类1,继承方式 基类2,…. {….};
。多个基类中可能包含同名变量或函数,可能会有大量的二义性。
多重继承中解决访问歧义的方法,明确指明要访问定义于哪个基类中的成员。基类名::数据成员名(或成员函数(参数表))
#include <iostream>
using namespace std;
class Bed
{
public:
Bed(int weight) : weight_(weight)
{
}
void Sleep()
{
cout << "Sleep ..." << endl;
}
int weight_;
};
class Sofa
{
public:
Sofa(int weight) : weight_(weight)
{
}
void WatchTV()
{
cout << "Watch TV ..." << endl;
}
int weight_;
};
class SofaBed : public Bed, public Sofa
{
public:
SofaBed() : Bed(0), Sofa(0)
{
FoldIn();
}
void FoldOut()
{
cout << "FoldOut ..." << endl;
}
void FoldIn()
{
cout << "FoldIn ..." << endl;
}
};
int main(void)
{
SofaBed sofaBed;
//sofaBed.weight_ = 10; error
//sofaBed.weight_ = 20; error
sofaBed.Bed::weight_ = 10;
sofaBed.Sofa::weight_ = 20;
sofaBed.WatchTV();
sofaBed.FoldOut();
sofaBed.Sleep();
return 0;
}
不能直接写 sofaBed.weight = 10;
因为sofaBed继承了Sofa和Bed,实际上有weigh的两份拷贝,这样指向不明。只能通过sofaBed.Bed::weight = 10;访问,但实际上一个sofaBed理应只有一个weight,下面通过虚基类和虚继承可以解决这个问题。
虚继承与虚基类
当派生类从多个基类派生,而这些基类又从同一个基类派生,则在访问此共同基类中的成员时,将产生二义性,可以采用虚基类来解决。
虚基类的声明
以virtual修饰说明基类 例:class B1:virtual public BB
虚基类的引入:用于有共同基类的场合,砖石型继承
。作用:主要用来解决多继承时可能发生的对同一基类继承多次而产生的二义性问题。为最远的派生类提供唯一的基类成员,而不重复产生多次拷贝
。
#include <iostream>
using namespace std;
class Furniture
{
public:
Furniture(int weight) : weight_(weight)
{
cout << "Furniture ..." << endl;
}
~Furniture()
{
cout << "~Furniture ..." << endl;
}
int weight_;
};
class Bed : virtual public Furniture
{
public:
Bed(int weight) : Furniture(weight)
{
cout << "Bed ..." << endl;
}
~Bed()
{
cout << "~Bed ..." << endl;
}
void Sleep()
{
cout << "Sleep ..." << endl;
}
};
class Sofa : virtual public Furniture
{
public:
Sofa(int weight) : Furniture(weight)
{
cout << "Sofa ..." << endl;
}
~Sofa()
{
cout << "~Sofa ..." << endl;
}
void WatchTV()
{
cout << "Watch TV ..." << endl;
}
};
class SofaBed : public Bed, public Sofa
{
public:
SofaBed(int weight) : Bed(weight), Sofa(weight), Furniture(weight)
{
cout << "SofaBed ..." << endl;
FoldIn();
}
~SofaBed()
{
cout << "~SofaBed ..." << endl;
}
void FoldOut()
{
cout << "FoldOut ..." << endl;
}
void FoldIn()
{
cout << "FoldIn ..." << endl;
}
};
int main(void)
{
SofaBed sofaBed(5);
sofaBed.weight_ = 10;
sofaBed.WatchTV();
sofaBed.FoldOut();
sofaBed.Sleep();
return 0;
}
此时只有一份weigh_,不存在访问歧义的问题。
- 虚基类的成员是由
最远派生类的构造函数通过调用虚基类的构造函数
进行初始化的。 - 在整个继承结构中,
直接或间接继承虚基类的所有派生类,都必须在构造函数的成员初始化表中给出对虚基类的构造函数的调用
。如果未列出,则表示调用该虚基类的默认构造函数。 - 在建立对象时,
只有最远派生类的构造函数调用虚基类的构造函数
,该派生类的其他基类对虚基类构造函数的调用被忽略
虚继承对C++对象内存模型造成的影响
虚基类表
基类指针指向派生类,访问虚基类成员。 间接访问,需要运行时的支持