类的继承与派生

一、类的继承与类的派生

继承的概念

通过已有的类建立新类的过程,叫做类的派生

原来的类称为基类,也称为父类或一般类;新类称为派生类,也称为子类或特殊类。

派生类的定义与大小

派生类的定义

在C++语言中,从基类派生派生类的格式

class 派生类名 : 继承方式说明符 基类名
{
  类体
};

继承方式说明符指明如何控制基类成员在派生类中的访问属性,通常有public、private和protected 3中方式。

例5-1 基类与派生类的定义

class BaseClass         //基类 
{
    int v1,v2;
};

class DerivedClass:public BaseClass     //派生类 
{
    int v3;
 };

空类也可以作为基类。

程序5-1 派生类该百年基类成员的访问权限

#include 
using namespace std;

class BaseClass
{
    public:
        int v1,v2;
        BaseClass():v1(1),v2(1){}
        int temp1(){}
};
 
class DerivedClass:public BaseClass
{
    int v1;
    int temp1(){}
    public:
        DerivedClass():v1(10){}
        void printv()
        {
            cout<<"v1="<

如果派生类Derived中重写了print()函数,若还想在函数中访问another的私有成员,则必须将类Derived的print()函数也声明为another的友元。

程序5-4 派生关系中的静态成员

#include 
using namespace std;
class Base
{
    private:
        float x;
    public:
        static int staV;
        Base()
        {
            staV++;
        }
};

int Base::staV = 0;

class Derived:public Base
{
    private:
        float y;
    public:
        Derived()
        {
            staV++;
        }
};

int main()
{
    Base a;
    cout<

有继承关系的类之间的访问

在类的派生层次结构中,基类的成员和派生类新增的成员都具有类作用域。二者的作用范围不同,是相互包含的两个层,派生类在内层,基类在外层。

程序5-5 访问基类和派生类成员的方式

#include 
using namespace std;

class CB
{
    public:
        int a;
        CB(int x)
        {
            a = x;
        }
        void showa()
        {
            cout<<"Class CB--a="<name = name;
}

string CStudent::GetName()
{
    return name;
}

void CStudent::SetId(string id)
{
    this->id = id;
}

string CStudent::GetId(){
    return id;
}

class CUndergraduateStudent:public CStudent     //本科生类,继承于类CStudent 
{
    private:
        string department;      //学生所属的系名
    public:
        void PrintInfo();
        void SetInfo(const string &,const string &,int,char,const string &); 
};

void CUndergraduateStudent::PrintInfo()
{
    CStudent::PrintInfo();  //调用基类的公有PrintInfo函数
    cout<<"院系:\t"<

程序5-7 类之间的访问
假设公司雇员分为雇员(employee)、经理(manager)、工程师(engineer)和高级主管(director)。各类的属性如下:

employee(雇员)类:姓名、年龄、工资;

manager(经理)类:姓名、年龄、工资、行政级别;

engineer(工程师)类:姓名、年龄、工资、专业、学位:

director(高级主管)类:姓名、年龄、工资、行政级别、职务。

将类employee 设计为基类,含有成员变量:姓名、年龄和工资。类manager 和类 engineer 是类employee的派生类,类director是类manager的派生类。

#include 
#include 
using namespace std;

class employee          //类employee将作为其他几个类的基类 
{
    short age;
    float salary;
    protected:
        string name;
    public:
        employee(short ag,float sa,string na)
        {
            age = ag;
            salary = sa;
            name = na;
        };
        void print()
        {
            cout<<"\n"<

protected访问范围说明符

基类中的保护成员可以在派生类的成员函数中被访问。

程序5-8 基类中的成员是私有成员时的访问方式

#include 
using namespace std;

class BaseClass
{
    int v1,v2;      //私有成员变量
    public:
        void SetValue(int m,int n)
        {
            v1 = m;
            v2 = n;
         } 
         void PrintValue();
};

void BaseClass::PrintValue()
{
    cout<<"v1="<

程序5-9 基类中保护成员的访问方式

#include 
using namespace std;

class BaseClass
{
    protected:
        int v1,v2;
    public:
    void SetValue(int m,int n)
        {
            v1 = m;
            v2 = n;
         } 
         void PrintValue();
};

void BaseClass::PrintValue()
{
    cout<<"v1="<

多重继承

C++允许从多个类派生一个类,即一个派生类可以同时有多个基类。这称为多重继承。

从一个基类派生一个派生类的情况,称为单继承或单重继承。

一个类从多个基类派生的格式

class 派生类名 : 继承方式说明符 基类名1,继承方式说明符 基类名2,...,继承方式说明符 基类名n
{
  类体
};

程序5-10 多重继承下的访问方式

#include 
using namespace std;

class CB1
{
    public:
        int a;      //重名
        CB1(int x)
        {
            a = x;
         } 
        void showa()        //重名
        {
            cout<<"Class CB1==>a="<a="<a="<各成员 
    派生类中 
    基类与派生类外 
    
   
   
    
    基类的公有成员 
    直接访问 
    直接访问 
    
    
    基类的保护成员 
    直接访问 
    调用公有函数访问 
    
    
    基类的私有成员 
    调用公有函数访问 
    调用公有函数访问 
    
    
    从基类继承的公有成员 
    直接访问 
    直接访问 
    
    
    从基类继承的保护成员 
    直接访问 
    调用公有函数访问 
    
    
    从基类继承的私有成员 
    调用公有函数访问 
    调用公有函数访问 
    
    
    派生类中定义的公有成员 
    直接访问 
    直接访问 
    
    
    派生类中定义的保护成员 
    直接访问 
    调用公有函数访问 
    
    
    派生类中定义的私有成员 
    直接访问 
    调用公有函数访问 
    
   
  
 

程序5-12 公有继承访问控制示例

#include 
#include 
using namespace std;

class Base
{
    public:
        int vBPub;
    protected:
        int vBPro;
    private:
        int vBPri;
    public:
        Base()
        {
            vBPub = 10;
            vBPro = 20;
            vBPri = 30;
        };
        void SetPriValue(int);
        void SetProValue(int,int);
        int GetPriValue();
        int GetProValue();
};

void Base::SetPriValue(int k)
{
    vBPri = k;
}

void Base::SetProValue(int m,int n)
{
    vBPro = m;
    vBPri = n;
}

int Base::GetPriValue()
{
    return vBPri;
}

int Base::GetProValue()
{
    return vBPro;
}

class Derived:public Base
{
    public:
        int vDPub,vBPub;
    protected:
        int vDPro;
    private:
        int vDPri;
    public:
        Derived()
        {
            vDPub = 100;
            vDPro = 200;
            vDPri = 300;
            vBPub = 15;
        };
        void SetPriValue(int);
        void SetProValue(int,int);
        int GetPriValue();
        int GetProValue();
        void PrintValue();
};

void Derived::SetPriValue(int k)
{
    vDPri = k;
}

void Derived::SetProValue(int m,int n)
{
    vDPro = m;
    vDPri = n;
    Base::vBPro = 2*m;
//  Base::vBPri = 2*n;      //不可以直接访问从基类继承的私有成员变量
     
}

int Derived::GetPriValue()
{
    return vDPri;
 } 
 
int Derived::GetProValue()
{
    return vDPro;
}

void Derived::PrintValue()
{
    cout<<"在派生类中访问基类"<

例5-11 修改程序5-15
将主函数修改如下:

int main()
{
    cout<<"带参数对象的创建"<

例5-12

int main()
{
    cout<<"无参对象的创建"<

程序5-16 调用基类和派生类的构造函数、析构函数和成员函数

#include 
using namespace std;

class Base
{
    private:
        int Y;
    public:
        Base(int y = 0)
        {
            Y = y;
            cout<<"Base("<

复制构造函数

程序5-17 派生类中的复制构造函数

#include 
using namespace std;

class A
{
    public:
        A()
        {
            i = 100;
            cout<<"类A默认构造函数"<

程序5-18 赋值运算符的重载及使用

#include 
using namespace std;

class CBase
{
    public:
        CBase(){}
        CBase(CBase & c)
        {
            cout<<"CBase::复制构造函数"<

多重继承的构造函数与析构函数

设计两个基类BaseClass1和BaseClass2共同派生一个派生类DerivedClass。

程序5-19 多重继承

#include 
using namespace std;
class BaseClass1
{
    protected:
        int v1,v2;
    public:
        BaseClass1();
        BaseClass1(int,int);
        ~BaseClass1();
        void SetValue(int,int);
        void PrintValue();
};

BaseClass1::BaseClass1():v1(0),v2(0)
{
    cout<<"BaseClass1 无参构造函数"<

四、类之间的关系

类与类之间的关系

使用已有类编写新的类有两种方式:继承和组合。

封闭类的派生

如果一个类的成员变量是另一个类的对象,则为封闭类。
定义封闭类构造函数的形式

类名::类名(形参表):内嵌对象1(形参表),内嵌对象2(形参表),...
{
  类体
}

程序5-20 封闭类的构造函数

#include 
#include 
using namespace std;

class myDate
{
    public:
        myDate();       //构造函数
        myDate(int);
        myDate(int,int);
        myDate(int,int,int);    //构造函数
        myDate(const myDate &d);
        ~myDate();
        void setDate(int,int,int);  //设置日期
        void setDate(myDate);    //设置日期
        myDate getDate();   //获取日期
        void setYear(int);  //设置年
        int getMonth();//获取月
        void printDate() const;     //打印日期
    private:
        int year,month,day;     //成员变量,表示年、月、日 
 };
//在类体外定义成员函数
myDate::myDate()
{
    year = 1970;
    month = 1;
    day = 1;
    cout<<"myDate默认构造函数"<

*互包含关系的类

在处理相对复杂的问题而需要考虑类的组合时,很可能遇到两个类相互引用的情况,称为循环依赖。

class A      //类A的定义
{
  public:
    void f(B b);    //以类B对象为形参的成员函数
};
class B        //类B的定义
{
  public:
    void g(A a);    //以类A对象为形参的成员函数
}

解决办法是使用前向引用声明。

在提供一个完整的类定义之前,不能定义该类的对象,也不能在内联成员函数中使用该类的对象。

例5-15 互包含的类

#include 
#include 
using namespace std;
class B;        //前向引用声明
class A
{
    int a;
    B b;            //不完整的类型定义 
};

class B
{
     A a;
     int b;
};

int main()
{
    return 0;
}

程序5-21 互包含的类

#include 
#include 
using namespace std;

class B;
class A
{
    public:
        int aInt;
        B *bPoint = NULL;
        void SetValue(int v)
        {
            aInt = v;
        }
};

class B
{
    public:
        A aCla;
        int bInt;
        void SetValue(int v)
        {
            bInt = v;
        }
};

int main()
{
    A ca;
    B cb;
    ca.bPoint = &cb;
    cout<<"ca.bPoint="<

将程序5-22的主函数修改如下

int main()
{
    cout<<"带参数对象的创建"<

六、基类与派生类指针的互相转换

对于指针类型,可以使用基类指针指向派生类对象,也可以将派生类的指针直接赋值给基类指针。
但即使基类指针指向的是一个派生类的对象,也不能通过基类指针访问基类中没有而仅在派生类中定义的成员函数。
当派生类指针指向基类对象时,必须要将基类对象进行强制类型转换,才能赋给派生类指针。

程序5-23 使用指针的情况

#include 
using namespace std;

class CBase
{
    protected:
        int n;
    public:
        CBase(int i):n(i){}
        void Print()
        {
            cout<<"CBase:n="<Print();      //调用的时派生类中的函数
    pBase = pDerived;       //基类指针 = 派生类指针,正确
    cout<<"使用基类指针调用函数"<Print();     //调用的是基类中的函数
    //pBase->Func();    //错误,通过基类指针不能调用派生类函数
    //pDerived = pBase  //派生类指针 = 基类指针
    pDerived = (CDerived *)pBase;   //强制类型转换,派生类指针 = 基类指针
    cout<<"使用派生类指针调用函数"<Print();  //调用的是派生类的函数
    return 0; 
}

使用派生类指针调用函数
CDerived:n=3
CDerived:v=6
使用基类指针调用函数
CBase:n=3
使用派生类指针调用函数
CDerived:n=3
CDerived:v=6

你可能感兴趣的:(类的继承与派生)