网站开发哪种语言好,在线crm系统是啥,在线设计平台用户规模,北京有名的装修公司目录 一、了解菱形继承
二、菱形继承的问题
三、虚拟继承virtual
3.1virtual
3.2虚拟继承解决数据冗余和二义性的原理
四、总结/继承和组合 一、了解菱形继承 单继承#xff1a;一个子类只有一个直接父类时称这个继承关系为单继承 多继承#xff1a;一个子类有两个或…目录 一、了解菱形继承
二、菱形继承的问题
三、虚拟继承virtual
3.1virtual
3.2虚拟继承解决数据冗余和二义性的原理
四、总结/继承和组合 一、了解菱形继承 单继承一个子类只有一个直接父类时称这个继承关系为单继承 多继承一个子类有两个或以上直接父类时称这个继承关系为多继承 菱形继承菱形继承是多继承的一种特殊情况。 二、菱形继承的问题 菱形继承的问题从下面的对象成员模型构造可以看出菱形继承有数据冗余和二义性的问题。 在Assistant的对象中Person成员会有两份。 class Person
{
public:string _name; // 姓名
};
class Student : public Person
{
protected:int _num; //学号
};
class Teacher : public Person
{
protected:int _id; // 职工编号
};
class Assistant : public Student, public Teacher
{
protected:string _majorCourse; // 主修课程
};
void Test()
{// 这样会有二义性无法明确知道访问的是哪一个Assistant a;a._name peter;// 需要显示指定访问哪个父类的成员可以解决二义性问题但是数据冗余问题无法解决a.Student::_name xxx;a.Teacher::_name yyy;
} 虚拟继承可以解决菱形继承的二义性和数据冗余的问题。如上面的继承关系在Student和 Teacher的继承Person时使用虚拟继承即可解决问题。需要注意的是虚拟继承不要在其他地 方去使用。 三、虚拟继承virtual
3.1virtual 虚拟继承可以解决菱形继承的二义性和数据冗余的问题。如上面的继承关系在Student和 Teacher的继承Person时使用虚拟继承即可解决问题。需要注意的是虚拟继承不要在其他地 方去使用。 class Person
{
public:string _name; // 姓名
};
class Student : virtual public Person
{
protected:int _num; //学号
};
class Teacher : virtual public Person
{
protected:int _id; // 职工编号
};
class Assistant : public Student, public Teacher
{
protected:string _majorCourse; // 主修课程
};
void Test()
{Assistant a;a._name peter;
} 3.2虚拟继承解决数据冗余和二义性的原理 为了研究虚拟继承原理我们给出了一个简化的菱形继承继承体系再借助内存窗口观察对象成 员的模型。 class A
{
public:int _a;
};
// class B : public A
class B : virtual public A
{
public:int _b;
};
// class C : public A
class C : virtual public A
{
public:int _c;
};
class D : public B, public C
{
public:int _d;
};
int main()
{D d;d.B::_a 1;d.C::_a 2;d._b 3;d._c 4;d._d 5;return 0;
} 下图是 菱形继承 的内存对象成员模型这里可以看到数据冗余 下图是 菱形虚拟继承 的内存对象成员模型这里可以分析出D对象中将A放到的了对象组成的最下 面这个A同时属于B和C那么B和C如何去找到公共的A呢这里是通过了B和C的两个指针指 向的一张表。这两个指针叫虚基表指针这两个表叫虚基表。虚基表中存的偏移量。通过偏移量 可以找到下面的A。 原理图 四、总结/继承和组合 1. C语法复杂其实多继承就是一个体现。有了多继承就存在菱形继承有了菱 形继承就有菱形虚拟继承底层实现就很复杂。所以一般不建议设计出多继承一定不要设 计出菱形继承。否则在复杂度及性能上都有问题。 2. 多继承可以认为是C的缺陷之一很多后来的OO语言都没有多继承如Java。 3. 继承和组合 首先在日常代码的编写过程中经常遵循一个理念 高内聚低耦合。 1.public继承是一种 is-a 的关系。也就是说每个派生类对象都是一个基类对象。 2.组合是一种 has-a 的关系。假设B组合了A每个B对象中都有一个A对象。 3.优先使用对象组合而不是类继承 。 4.继承允许你根据基类的实现来定义派生类的实现。这种通过生成派生类的复用通常被称 为白箱复用(white-box reuse)。术语“白箱”是相对可视性而言在继承方式中基类的 内部细节对子类可见 。继承一定程度破坏了基类的封装基类的改变对派生类有很 大的影响。派生类和基类间的依赖关系很强耦合度高。 5.对象组合是类继承之外的另一种复用选择。新的更复杂的功能可以通过组装或组合对象 来获得。对象组合要求被组合的对象具有良好定义的接口。这种复用风格被称为黑箱复 用(black-box reuse)因为对象的内部细节是不可见的。对象只以“黑箱”的形式出现。 组合类之间没有很强的依赖关系耦合度低。优先使用对象组合有助于你保持每个类被 封装。 6.实际尽量多去用组合。组合的耦合度低代码维护性好。不过继承也有用武之地的有 些关系就适合继承那就用继承另外要实现多态也必须要继承。类之间的关系可以用 继承可以用组合就用组合。 // Car和BMW Car和Benz构成is-a的关系
class Car {
protected:string _colour 白色; // 颜色string _num 豫A88888; // 车牌号
};class BMW : public Car {
public:void Drive() { cout 好开-操控 endl; }
};class Benz : public Car {
public:void Drive() { cout 好坐-舒适 endl; }
};// Tire和Car构成has-a的关系class Tire {
protected:string _brand Michelin; // 品牌size_t _size 17; // 尺寸};class Car {
protected:string _colour 白色; // 颜色string _num 豫A88888; // 车牌号Tire _t; // 轮胎
};