做1688网站到哪里找图片,网站建设企业 熊账号,微信如何做自己的网站,长沙建立网站多继承#xff08;Multiple Inheritance#xff09;
是指从多个直接基类中产生派生类的能力#xff0c;多继承的派生类继承了所有父类的成员。尽管概念上非常简单#xff0c;但是多个基类的相互交织可能会带来错综复杂的设计问题#xff0c;命名冲突就是不可回避的一个。…多继承Multiple Inheritance
是指从多个直接基类中产生派生类的能力多继承的派生类继承了所有父类的成员。尽管概念上非常简单但是多个基类的相互交织可能会带来错综复杂的设计问题命名冲突就是不可回避的一个。
注意 多继承时很容易产生命名冲突即使我们很小心地将所有类中的成员变量和成员函数都命名为不同的名字命名冲突依然有可能发生比如典型的是菱形继承。 #mermaid-svg-fQIzMuuYpiJzRYYu {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-fQIzMuuYpiJzRYYu .error-icon{fill:#552222;}#mermaid-svg-fQIzMuuYpiJzRYYu .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-fQIzMuuYpiJzRYYu .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-fQIzMuuYpiJzRYYu .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-fQIzMuuYpiJzRYYu .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-fQIzMuuYpiJzRYYu .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-fQIzMuuYpiJzRYYu .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-fQIzMuuYpiJzRYYu .marker{fill:#333333;stroke:#333333;}#mermaid-svg-fQIzMuuYpiJzRYYu .marker.cross{stroke:#333333;}#mermaid-svg-fQIzMuuYpiJzRYYu svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-fQIzMuuYpiJzRYYu .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-fQIzMuuYpiJzRYYu .cluster-label text{fill:#333;}#mermaid-svg-fQIzMuuYpiJzRYYu .cluster-label span{color:#333;}#mermaid-svg-fQIzMuuYpiJzRYYu .label text,#mermaid-svg-fQIzMuuYpiJzRYYu span{fill:#333;color:#333;}#mermaid-svg-fQIzMuuYpiJzRYYu .node rect,#mermaid-svg-fQIzMuuYpiJzRYYu .node circle,#mermaid-svg-fQIzMuuYpiJzRYYu .node ellipse,#mermaid-svg-fQIzMuuYpiJzRYYu .node polygon,#mermaid-svg-fQIzMuuYpiJzRYYu .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-fQIzMuuYpiJzRYYu .node .label{text-align:center;}#mermaid-svg-fQIzMuuYpiJzRYYu .node.clickable{cursor:pointer;}#mermaid-svg-fQIzMuuYpiJzRYYu .arrowheadPath{fill:#333333;}#mermaid-svg-fQIzMuuYpiJzRYYu .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-fQIzMuuYpiJzRYYu .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-fQIzMuuYpiJzRYYu .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-fQIzMuuYpiJzRYYu .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-fQIzMuuYpiJzRYYu .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-fQIzMuuYpiJzRYYu .cluster text{fill:#333;}#mermaid-svg-fQIzMuuYpiJzRYYu .cluster span{color:#333;}#mermaid-svg-fQIzMuuYpiJzRYYu div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-fQIzMuuYpiJzRYYu :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} A B C D 基类 A 派生出类 B 和类 C子类 D 继承自类 B 和类 C。 这个时候类 A 中的成员变量和成员函数继承到类 D 中变成了两份一份来自 A–B–D 这条路径另一份来自 A–C–D 这条路径。
这样的问题在于在D类中使用或者访问基类A中的成员函数、成员变量时会产生歧义。编译器不知道它是来着A–B–D还是来自A–C–D这条路径。
//间接基类A
class A{
protected:int m_a;
};//直接基类B
class B: public A{
protected:int m_b;
};//直接基类C
class C: public A{
protected:int m_c;
};//派生类D
class D: public B, public C{
public:void seta(int a){ m_a a; } //命名冲突void setb(int b){ m_b b; } //正确void setc(int c){ m_c c; } //正确void setd(int d){ m_d d; } //正确
private:int m_d;
};int main(){D d;return 0;
}这段代码实现了上图所示的菱形继承D类中成员函数代码试图直接访问成员变量 m_a结果发生了错误因为类 B 和类 C 中都有成员变量 m_a从 A 类继承而来编译器不知道选用哪一个所以产生了歧义。
为了消除歧义可以在访问的时候给他标明是来自哪一个类的比如以下代码
void seta(int a){ C::m_a a; } //表明这个成员函数是通过 A--C--D 这条路径//或者这样
void seta(int a){ B::m_a a; } //表明这个成员函数是通过 A--B--D 这条路径虚继承Virtual Inheritance
为了解决多继承时的命名冲突和冗余数据问题C 提出了虚继承使得在派生类中只保留一份间接基类的成员。 在继承方式前面加上 virtual 关键字就是虚继承比如以下代码中展示的
//间接基类A
class A{
protected:int m_a;
};//直接基类B
class B: virtual public A{ //虚继承
protected:int m_b;
};//直接基类C
class C: virtual public A{ //虚继承
protected:int m_c;
};//派生类D
class D: public B, public C{
public:void seta(int a){ m_a a; } //正确void setb(int b){ m_b b; } //正确void setc(int c){ m_c c; } //正确void setd(int d){ m_d d; } //正确
private:int m_d;
};int main(){D d;return 0;
}这段代码使用虚继承重新实现了上图所示的菱形继承这样在派生类 D 中就只保留了一份成员变量 m_a直接访问就不会再有歧义了。
虚继承的目的是让某个类做出声明承诺愿意共享它的基类。其中这个被共享的基类就称为虚基类Virtual Base Class本例中的 A 就是一个虚基类。在这种机制下不论虚基类在继承体系中出现了多少次在派生类中都只包含一份虚基类的成员。 #mermaid-svg-XQOuIY1QcmmrQw7C {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-XQOuIY1QcmmrQw7C .error-icon{fill:#552222;}#mermaid-svg-XQOuIY1QcmmrQw7C .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-XQOuIY1QcmmrQw7C .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-XQOuIY1QcmmrQw7C .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-XQOuIY1QcmmrQw7C .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-XQOuIY1QcmmrQw7C .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-XQOuIY1QcmmrQw7C .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-XQOuIY1QcmmrQw7C .marker{fill:#333333;stroke:#333333;}#mermaid-svg-XQOuIY1QcmmrQw7C .marker.cross{stroke:#333333;}#mermaid-svg-XQOuIY1QcmmrQw7C svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-XQOuIY1QcmmrQw7C .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-XQOuIY1QcmmrQw7C .cluster-label text{fill:#333;}#mermaid-svg-XQOuIY1QcmmrQw7C .cluster-label span{color:#333;}#mermaid-svg-XQOuIY1QcmmrQw7C .label text,#mermaid-svg-XQOuIY1QcmmrQw7C span{fill:#333;color:#333;}#mermaid-svg-XQOuIY1QcmmrQw7C .node rect,#mermaid-svg-XQOuIY1QcmmrQw7C .node circle,#mermaid-svg-XQOuIY1QcmmrQw7C .node ellipse,#mermaid-svg-XQOuIY1QcmmrQw7C .node polygon,#mermaid-svg-XQOuIY1QcmmrQw7C .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-XQOuIY1QcmmrQw7C .node .label{text-align:center;}#mermaid-svg-XQOuIY1QcmmrQw7C .node.clickable{cursor:pointer;}#mermaid-svg-XQOuIY1QcmmrQw7C .arrowheadPath{fill:#333333;}#mermaid-svg-XQOuIY1QcmmrQw7C .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-XQOuIY1QcmmrQw7C .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-XQOuIY1QcmmrQw7C .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-XQOuIY1QcmmrQw7C .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-XQOuIY1QcmmrQw7C .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-XQOuIY1QcmmrQw7C .cluster text{fill:#333;}#mermaid-svg-XQOuIY1QcmmrQw7C .cluster span{color:#333;}#mermaid-svg-XQOuIY1QcmmrQw7C div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-XQOuIY1QcmmrQw7C :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 虚继承 虚继承 A B C D 必须在虚派生的真实需求出现前就已经完成虚派生的操作 虚派生只影响从指定了虚基类的派生类中进一步派生出来的类它不会影响派生类本身 理由 在上图中当定义 D 类时才出现了对虚派生的需求但是如果 B 类和 C 类不是从 A 类虚派生得到的那么 D 类还是会保留 A 类的两份成员。
建议能用单一继承解决的问题就不要使用多继承