C++ 继承性:派生类

C++继承性:派生类

  1. 继承:继承是面向对象程序设计的一个重要机制,该机制自动地为一个类提供来自另一个类的操作和数据结构,这使程序员只需在新类中定义已有类中没有的成员来建立新类。即,它允许在既有类的基础上来创建新的类,新类可以从一个或多个既有类中继承函数和数据,可以重新定义或加进新的数据和函数,从而新类不但可以共享原有类的属性,并且具有新的特性,这样就形成类的层次。

  2. 在C++中,通过继承,可以让一个类拥有另一个类的全部属性,或者说是让一个类继承另一个类的全部属性。把被继承的类称为基类或者父类,而继承的类或者说是派生出来的新类称之为派生类或者子类。

  3. 如果对于一个派生类只有一个基类,称为单继承。如果同时有多个基类,称为多重继承。

  4. 特点:C++中类的继承层次自然地表达了人们分析问题时所用的分类结构,从而使得软件具有可重用性。大大改善了软件系统的可理解性和可维护性派生类实现了代码的重用,减少重复的工作量。

  5. 单继承:一般来讲,只有一个基类的派生类称为单继承,其形式如下:

    class派生类名:继承方式 基类名

    {

         派生类成员定义;

    };

    声明中的“基类名”是已有的类的名称,“派生类名”是继承原有类的特征而生成的新类名称。基类必须在声明派生类之前就已经声明过,否则会出现编译错误,“继承方式”制定了派生类成员以及类外对象对于派生类从基类继承来的成员的访问权限,其关键字为public,private和protected,分别表示它们的继承方式是公有继承(公有派生),私有继承(私有派生)和保护继承(保护派生),如果省略,系统将默认为私有继承

    1:公有继承访问权限特征:当类继承方式为公有继承时,基类中的公有成员和保护成员的访问权限在派生类中保持不变,而基类的私有成员不可访问。也就是说,基类的公有成员和保护成员被派生类继承过来作为派生类的公有和保护成员,而基类的私有成员在派生类中不能直接使用。

    #include<iostream>

    using  namespace std;

    classA   //基类A的定义

    {

         public:

             void setx(int m) {x=m;}

             void sety(int n) {y=n;}

             int getx() const{   return x;}

             int gety() const{   return y;}

         protected:

             int x;

         private:

             int y;

    }

    classB:public A//派生类B对基类A的公有继承

    {

    public:

         int getsum() {return x+gety();}//直接访问从基类继承来的保护成员x;但基类的私有成员y,只能通过接口函数访问

    };

    main()

    {

         B b;

         b.setx(5);

         b.sety(8);

         cout<<”X =”<<b.get()<<endl;//访问基类的公有成员函数

         cout<<”X+Y=”<<b.getsum()<<endl;//访问派生类的公有成员函数

    }

  6. 私有继承:当类继承方式为私有继承时,基类中的公有成员和保护成员都将以私有成员身份出现,基类的私有成员与公有继承相同,不可访问。也就是说,基类的公有成员和保护成员和保护成员被派生类继承过来作为派生类的私有成员,而基类的私有成员在派生类中不能直接使用。

    classA//基类A的定义

    {

         public:

             void setx(int m) {x=m;}

             void sety(int n) {y=n;}

             int getx() const{return x;}

             int gety() const{return y;}

         protected:

             int x;

         private:

             int y;

    };

    classB:private A//派生类B对基类A的私有继承

    {

         public:

             void setBx(int m) {x=m;}

             void setBy(int n) {y=n;}

             int getBx() const { return getx();}

             int getBy() const { return gety();}

             intgetsum() {return x+gety();} //直接访问从基类继承来的保护成员x,但基类的私有成员y,只能通过接口函数访问。

    };

    main()

{

     B b;

     b.setBx(5);

b.setBy(8);

cout<<”X=”<<b.getBx()<<endl;

cout<<”X+Y”<<b.getsum()<<endl;//访问派生类的公有成员函数

}

基类A派生出新的B类,其继承方式是私有继承。在基类A中声明的公有和保护的数据成员和成员函数被类B继承过来作为自身的私有成员。因此,派生类B的对象无法直接访问基类A中的任一成员。

基类成员

基类私有成员

基类公有成员

继承方式

私有

公有

私有

公有

派生类成员

不可访问

不能访问

可访问

可访问

外部函数

不可访问

不能访问

不可访问

可访问

  1. 保护继承:保护成员可以被派生类的成员函数访问,但是对于外界是隐藏起来的,外部函数不能访问它。当类继承方式为保护继承时,基类中的公有成员和保护成员都将以保护成员身份出现,基类的私有不可访问。也就是说,基类的公有成员和保护成员被派生类继承过来作为派生类的保护成员,而基类的私有成员在派生类中不能直接使用。

    公有成员----à保护成员

    保护成员----à保护成员

    私有成员----à不能直接使用

  2. 派生类的构造函数和析构函数:

    1:当创建派生类对象时,首先执行基类的构造函数,随后再执行派生类的构造函数;当撤销派生类对象时,析构函数的执行顺序则正好与构造函数的顺序相反,即先执行派生类的析构函数,随后再执行基类的析构函数。换句话说,构造函数按其引入的顺序执行,析构函数按其引入的相反顺序执行。

    2:当基类含有带参数的构造函数时,派生类的构造函数必须说明基类所需要的所有参数,其构造函数一般格式如下:

    派生类构造函数名(参数表):基类构造函数名(参数表)

{

……

}

Eg:student(intn,char name[],char s,int a,char ad[]):stud(n,name,s)

3:派生类构造函数后面括号内的参数表包括参数的类型和参数名。基类构造函数后面括号内的参数表只包括参数的参数名而不包括参数的类型。而派生类中含有对象成员时,其构造函数一般格式如下。

派生类构造函数名(参数表):基类构造函数名(参数表),对象成员名(参数表)

{

    ……

}

在定义派生类对象时,构造函数的执行顺序如下:

  1. 基类的构造函数

  2. 对象成员的构造函数

  3. 派生类的构造函数

class stud//基类stud

{

proteted:

    int num;

    char name[10];

    char sex;

public:

    stud(int n,char nam[],char s)

{

    num=n;

    strcpy(name,nam);

    sex=s;

}

~stud(){}

};

class student:public stud//派生类student

{

    private:

        intage;

        charaddr[30];

    public:

        student(intn,char nam[],char s,int a,char ad[]):stud(n,nam,s)

{

    age=a;

    strcpy(addr,ad);

}

voidshow()

{

cout<<”num:”<<num<<endl;

cout<<”name:”<<name<<endl;

cout<<”sex:”<<sex<<endl;

cout<<”age:”<<age<<endl;

cout<<”address:”<<address<<endl;

}

~student(){ }

};

void main()

{

    student(10010,”wang_li”,’f’,19,”115BeijingRoad,Shanghai”);

    student(10011,”Zhang_zhou”,’m’,20,”213BeijingRoad,Shanghai”);

a.show();

b.show();

}

        4:1)由于析构函数是不带参数的,在派生类中是否要定义析构函数与它所属的基类无关,故基类的析构函数不会因为派生类没有析构函数而得不到执行,它们各自是独立的。

          2)当基类构造函数不带参数时,派生类不一定需要定义构造函数,然而当基类的构造函数带有至少一个参数,它所有的派生类都必须定义构造函数。

9】多重继承:一个派生类有两个或者两个以上的基类的派生类称为多重继承或多继承。多继承可以看作是单继承的组合,单继承可以看作是多继承的特例。每一个基类必须制定其继承的方式,如果省略,相应的基类则取私有继承类型,而不是和前一个基类取相同的继承类型。各个基类构造函数的执行顺序取决于派生类时所制定的各个基类的顺序,而与派生类构造函数的成员初始化列表中给定的基类顺序无关。

Egclass 派生类名:继承方式基类名1,继承方式 基类名2……,继承方式 基类名n

{

        派生类成员定义;

}

class D:public A,public B,public C

{

    ……

}

  1. 虚基类:1:声明形式:class 派生类名:virtual派生类型 基类名

    Eg:  class B{private:int b;}

         class B1:virtual public B{private:int b1;};

         2:虚基类的应用:

             1)主要用来解决多继承时可能发生的对同一基类继承多次而产生的二义性问题。

             2)为最远的派生类提供唯一的基类成员,而不重复产生多次拷贝。

             3)在第一级继承时就要将共同基类设计为虚基类。

阅读更多
文章标签: C++
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭