zoukankan      html  css  js  c++  java
  • VC++之 继承(二)

    C++多重继承的概念

    由多个基类共同派生出派生类的继承结构称为多重继承多继承(multiple-inheritance)。

    多重继承是从实际的需要产生的。例如:从大学在册人员产生学生和教职工。再从学生派生研究生。如果考虑到研究生可以当助教,那么他们又有了教职工的特性。教职工可分为教师和行政人员,但行政人员也可以去授课,兼有教师的特点等。这就是多继承,其继承关系如下图所示。



    图 大学在册人员继承关系

    多重继承下的歧义性问题及解决

    问题1:教职工兼研究生,在其基类“教职工”中有一个“身份证号”,另一基类“研究生”中也有一个“身份证号”,如果只讲他的身份证号那么是哪一个基类中的呢?这两者可能是一回事,但计算机系统并不这么认为。

    问题2:两个基类中可能也各有一个“职务”,这两者可能根本不同,一个是教职工的,一个是研究生的。但它们的标识符是一样的,这就会出现二义性。

    解决办法

    1. 类似于“职务”这样的成员可以用不同标识符来区分。
    2. 但“身份证号”不行,因为这是由两个基类“教职工”和“研究生”共同的基类“在职人员”类继承来的,只有同一个标志符。即唯一标识问题,通常采用作用域分辨符“::”:
          基类名::成员名; //数据成员
          基类名::成员名(参数表); //函数成员


    举例:下图为在职研究生派生类关系



    根据图中显示的派生关系,定义EGStudent类对象EGStudent1,并假定派生全部为公有派生,而int No全为公有成员,其含义如下所述:
        EGStud1.No //在职学号
        EGStud1.GStudent::No //研究生号
        EGStud1.GStudent.Student::No //学生号,此处只为了说明成员唯一标识
        EGStud1.GStudent.Student.Person::No //身份证号
        EGStud1.Employee::No //工作证号
        EGStud1.Employee.Person::No //身份证号

    派生类成员标识的进一步说明

    EGStud1.GStudent.Student.Person::No和EGStud1.Employee.Person::No这两个身份证号从逻辑上讲应是一回事,但是物理上分配了不同内存空间,是两个变量,请参见下图(图中蓝色框为相应类的对象)。


    若class Person的身份证号标识为 int IdPerson,则可写为:
        EGStud1.GStudent::IdPerson
        EGStud1.Employee::IdPerson
    采用有确定字面意思的标识符,可以被编译器简单区分出来,且不必标出那么多层次的类,但写EGStud1.IdPerson是错的。

    作用域分辨符不能嵌套使用,如下面的描述均是错误的:
        EGStud1.GStudent::Student::No //学生号
        EGStud1.GStudent::Student::Person::No //身份证号

    应用举例

    【例8.2】由圆和高多重继承派生出圆锥。因为公有派生时,在派生类中不可以直接访问基类的私有成员,但可以直接访问基类的保护成员,所以当需要在派生类中访问基类的数据成员时,可以将它们定义为保护的,而不是私有的。 

    //【例8.2】由圆和高多重继承派生出圆锥。
    #include<iostream>
    #include<cmath>
    using namespace std;
    
    class Circle{
    protected:
        float x,y,r;                    //(x,y)为圆心,r为半径
    public:
        Circle(float a=0,float b=0,float R=0){x=a;y=b;r=R;}
        void Setcoordinate(float a,float b){x=a;y=b;}
        void Getcoordinate(float &a,float &b){a=x;b=y;}
        void SetR(float R){r=R;}
        float GetR(){return r;}
        float GetAreaCircle(){return float(r*r*3.14159);}
        float GetCircumference(){return float(2*r*3.14159);}
    };
    class Line{
    protected:
        float High;
    public:
        Line(float a=0){High=a;}
        void SetHigh(float a){High=a;}
        float GetHigh(){return High;}
    };
    class Cone:public Circle,public Line{
    public:
        Cone(float a,float b,float R,float d):Circle(a,b,R),Line(d){}
        float GetCV(){return float(GetAreaCircle()*High/3);}
        float GetCA(){
            return float(GetAreaCircle()+r*3.14159*sqrt(r*r+High*High));
        }//共有派生类中能直接访问直接基类的保护成员
    };
    
    int main(){
        Cone c1(5,8,3,4);
        float a,b;
        cout<<"圆锥体积:"<<c1.GetCV()<<'
    ';
        cout<<"圆锥表面积:"<<c1.GetCA()<<'
    ';
        cout<<"圆锥底面积:"<<c1.GetAreaCircle()<<'
    ';
        cout<<"圆锥底周长:"<<c1.GetCircumference()<<'
    ';
        cout<<"圆锥底半径:"<<c1.GetR()<<'
    ';
        c1.Getcoordinate(a,b);
        cout<<"圆锥底圆心坐标:("<<a<<','<<b<<")
    ";
        cout<<"圆锥高:"<<c1.GetHigh()<<'
    ';
        return 0;
    }
  • 相关阅读:
    RabbitMQ学习之:(八)Topic Exchange (转贴+我的评论)
    RabbitMQ学习之:(六)Direct Exchange (转贴+我的评论)
    抽象类
    开闭原则
    反射
    解决默认方法冲突
    单一职责原则
    java四种访问修饰符
    Java中基本类型和包装类
    方法在继承过程中可能出现的问题
  • 原文地址:https://www.cnblogs.com/delphi2014/p/4060052.html
Copyright © 2011-2022 走看看