C++ 继承和派生

版权声明:本文为博主原创文章,未经博主允许转载将负法律责任。 https://blog.csdn.net/ningmengbaby/article/details/82953695

定义:从一个或多个以前定义的类(基类)产生新类的过程称为派生,这个新类称为派生类。派生的新类同时可以增加或者重新定义数据和操作,这就产生了类的层次性。

类的继承是指派生类继承基类的数据成员和成员函数。继承常用来表示类属关系,不能将继承理解为构成关系。
当从现有类派生出新类时,派生类可以有如下几种变化:
  (1)增加新的成员(数据成员或成员函数)
(2)重新定义已有的成员函数
(3)改变基类成员的访问权限。
由此可见,基类定义了对象的一个集合,派生类通过增添新的成员限制该定义,以便定义这个集合的一个子集。C++派生类使用两种基本的面向对象技术:第一种称为性质约束,即对基类的性质加以限制;第二种称为性质扩展,即增加派生类的性质。
1.单一继承
1.1 单一继承的一般形式
在c++中,声明单一继承的一般形式如下:
class 派生类名:访问控制 基类名{
    private:
        成员声明列表
    protected:
        成员声明列表
    public:
        成员声明列表
};
这里用关键字class声明一个新的类。冒号后面的部分指示这个新类是哪个基类的派生类。所谓“访问控制”是指如何控制基类成员在派生类中的访问属性,它是3个关键字Public 、protected和private中的一个。一对大括号"{}"中是用来声明派生类自己的成员的。
使用内联函数实现单一继承
#include <iostream>
using namespace std;
class Point{
    private:
        int x,y;
    public:
        Point(int a,int b){x=a;y=b;cout<<"Point..."<<endl;}
        void Showxy(){cout<<"x="<<x<<",y=" <<y<<endl;}
        ~Point(){cout<<"Delete Point"<<endl;}
};
class Rectangle : public Point{
    private:
        int H,W;
    public:
        Rectangle(int a,int b,int h,int w):Point(a,b)         //构造函数初始化列表
        {H = h;W= w; cout<<"Rectangle..."<<endl;};
        void Show(){cout<< "H="<<H<<",W="<<endl;}
        ~Rectangle(){cout<<"Delete Rectangle" <<endl;}
};
void main(){
    Rectangle r1(3,4,5,6);
    r1.Showxy();                                       //派生类对象调用基类的成员函数
    r1.Show();                                         //派生类对象调用派生类的成员函数
}
程序输入如下:
Point...                                                   //调用基类构造函数
Rectangle...                                            //调用派生类构造函数
x=3,y=4                                                 //调用基类成员函数Showxy()
H=5,W=6                                                 //调用派生类的成员函数Show();
Delete Rectangle                                        //调用派生类的析构函数
Delete Point                                            //调用基类的析构函数
在派生类中继承的基类成员的初始化,需要由派生类的构造函数调用基类的构造函数来完成。
定义派生类的构造函数的一般形式如下:
派生类名::派生类名(参数表0):基类名(参数表)
构造函数(包括析构函数)是不被继承的,所以一个派生类只能调用它的直接基类的构造函数。当定义派生类的一个对象时,首先调用基类的构造函数,对基类成员进行初始化,然后执行派生类的构造函数,如果某个基类仍是一个派生类,则这个过程递归进行。当该对象消失时,析构函数的执行顺序和执行构造函数时的顺序正好相反。输出结果也证实了这个结论。
1.2类的保护成员
在类声明中,关键字protected之后声明的是类的保护成员。保护成员具有私有成员和公有成员的双重角色:对派生类的成员函数来货,它是公有成员,可以被访问;而对其他函数而言仍是私有成员,不能被访问。因此,要想在类Rectangle中使用统一的Show函数,只要把x和y定义成类Point的保护成员就行了。
1.3访问权限和赋值兼容规则
在公有派生情况下,基类成员的访问权限在派生类中保持不变。这就意味着在程序中:
(1)基类的公有成员在派生类中仍然是公有的。
(2)基类的保护成员在派生类中仍然是保护的。
(3)基类的不可访问的和私有的成员在派生类中仍然也是不可访问的。
在根类中,没有成员是不可访问的。对于根类来说,可能的访问级别是private、public和protected。但是在派生类中,可以存在第4种访问级别:不可访问(inaccessible)。例如在派生类Rectangle中,就不可以访问基类Point的数据成员x和y。不可访问成员总是从基类继承来的,要么是基类的不可访问成员,要么是基类的私有成员。因此,在公有派生的情况下,可以通过定义派生类自己的成员函数来访问派生类对象继承来的公有和保护成员,但是不能够访问继承来的私有成员。当希望类的某些成员能够被派生类所访问,而又不被其他的外界函数访问的时候,就应当把它们定义为保护的。
私有派生
#include <iostream>
using namespace std;
class Point{
    private:
        int x,y;
    public:
        Point(int a,int b){x=a;y=b;cout<<"Point..."<<endl;}
        void Show(){cout<<"x="<<x<<",y=" <<y<<endl;}
};
class Rectangle : private Point{
    private:
        int H,W;
    public:
        Rectangle(int a,int b,int h,int w):Point(a,b)         //构造函数初始化列表
        {H = h;W= w;}
        void Show(){Point::Show();cout<< "H="<<H<<",W="<<endl;}
};
class Test:public Rectangle{
    public:
        Test(int a,int b,int h,int w):Rectangle(a,b,h,w){}
        void Show(){Rectangle::Show();}
};
在这个例子中,基类的公有成员函数Show通过私有派生成了派生类Rectangle的私有成员函数,Test虽然是公有派生,但它已经无法使用基类Point的Show函数,即不能通过“Point::Show();”方式使用Point类的show函数,这就彻底切断了基类和外界的联系。私有派生的这一特点不利于进一步派生,因而实际中私有派生使用得并不多。
保护派生
派生也可以使用protected。这种派生使原来的权限都降一级使用,即private变为不可访问;protected变为private;public变为protected。因为限制了数据成员和成员函数的访问权限,所以使用得较少。它与private继承的主要区别主要在下一级的派生中。如果将上例Rectangle改为如下的保护继承方式:
    class Rectangle:protected Point {// 类体};
则在Test类中可以使用基类的Show函数,则下面函数的定义是正确的:
    class Test:public Rectangle{
            public:
                Test(int a,int b,int h,int w):Rectangle(a,b,h,w){}
                void Show(){Point::show();Rectangle::Show();}
    };
多重继承
一个类从多个基类派生的一般形式如下:
class 类名1:访问控制 类名2,访问控制 类名3,...,访问控制 类名n 
{...//定义派生类自己的成员};

猜你喜欢

转载自blog.csdn.net/ningmengbaby/article/details/82953695