C++继承(一) 常用的继承方式

一、继承简介

继承性是面向对象程序设计最重要的特征,可以说,不掌握继承就不等于掌握类和对象的精华,所以说继承是C++中很重要的一部分。
通过继承,我们可以用原来的数据类型来定义一个新的数据类型,定义的新类型既有原来数据中的成员,也能自己添加新的成员
我们一般把原来的数据类型称为基类或者父类,新的数据类型为派生类,或者子类在本篇博客中Base为基类,Deriver为派生类

继承的分类

单继承
#include<iostream>
using namespace std;
class Base
{
public:
int i = 1;
};
class Derive:public Base
{
public:
int b = 2;
};
int main()
{
Derive d1;
cout << sizeof(d1) << endl;
return 0;
}

单继承后派生类的大小
单继承的指向图:
这里写图片描述
在继承中箭头所指向的地方是有派生类指向基类;
在单继承中,定义的格式:

    class 派生类名:继承方式 基类名 
    {
        派生类成员
    };

在继承中继承方式有3中,刚刚上面只写了一个public的共有继承;
● public 表示公有继承
● private 表示私有继承
● protected 表示保护继承

多继承
class Base1
{
public:
    int a = 1;
};
class Base2
{
public:
    int b = 2;
};
class Derive:public Base1, public Base2
{
    int c = 3;
};

这里写图片描述
多继承的指向图:

在继承中箭头所指向的地方是有派生类指向基类;
在多继承中,定义的格式:

    class 派生类名:继承方式 基类名,继承方式 基类名
    {
        派生类成员;
    };

二、派生类的构成

派生类的组成一般就两部分,一部分是从基类继承过来的,第二部分是自己特有的;
所以在单继承中我的示意图Derive比Base的图大点,有存放自己特色的空间;
主要注意的是多继承中空间的分布:
这里写图片描述
在多继承中靠派生类近的基类属于先声明的,所以数据在派生类中最先被保存;
所以说,在多继承中,派生类的数据模型和继承顺序有很大关系

三、三种继承方式

我们在前面学类的时候就知道:public,protected,private的访问权限

访问方式类里面类外面
public允许访问允许访问
protected允许访问不允许访问
private允许访问不允许访问

这三种访问权限,在继承方式后也有所改变了

1,public继承
class Base
{
public:
    Base(int a = 0, int b = 0, int c = 0)
        : _pub(a)
        , _pro(b)
        , _pri(c)
    {}
    int _pub = 1;
protected:
    int _pro = 2;
private:
    int _pri = 3;
};
class Derive :public Base
{
public:
    void display()
    {
        cout << "_pub" << _pub << endl;
        cout << "_pro" << _pro << endl;
        cout << "_pri" << _pri << endl;
    }
};

在public继承中,派生类访问基类的private成员时就会报错:
这里写图片描述

2,protected继承
class Base
{
public:
    Base(int a = 0, int b = 0, int c = 0)
        : _pub(a)
        , _pro(b)
        , _pri(c)
    {}
    int _pub = 1;
protected:
    int _pro = 2;
private:
    int _pri = 3;
};
class Derive :protected Base
{
public:
    void display()
    {
        _pro = 10;
    }
};
int main()
{
    Derive d1;
    d1._pub = 4;
    d1._pro = 5;
    d1._pri = 6;
    return 0;
}

在protected继承中在派生类中可以访问基类中的protected成员,但是在main函数中_pub和_pro都不能被访问了;
这里写图片描述
如果你想要成员能在函数内部被访问,在函数外面不能被访问就用protected继承,可以说protected就是为继承而生的

3,private继承
class Base
{
public:
    Base(int a = 0, int b = 0, int c = 0)
        : _pub(a)
        , _pro(b)
        , _pri(c)
    {}
    int _pub = 1;
protected:
    int _pro = 2;
private:
    int _pri = 3;
};
class Derive :private Base
{
public:
    void display()
    {
        _pub = 20;
        _pro = 10;
        _pri = 30;
    }
};
int main()
{
    Derive d1;
    d1._pub = 4;
    d1._pro = 5;
    d1._pri = 6;
    return 0;
}

在私有继承中,从基类继承下来的东西全部就变为了派生类私有的,所以你在外部完全访问不了,或许有人认为在外部访问不了和protected继承好像没什么区别,你从再次创建一个派生类来访问它的protected成员时是可以访问的,但是private成员就访问不了;

总结一下三种继承方式
继承方式基类的public成员基类的protected成员基类的private成员继承引起的访问控制关系变化概括
public继承仍为public成员仍为protected成员不可见基类的非私有长远在子类的访问属性不变
protected继承变为protected成员变为protected成员不可见基类的非私有成员都为子类的保护成员
private继承变为private成员变为private成员不可见基类中的非私有成员都称为子类的私有成员

在继承中不管是单继承还是多继承,都要注明继承方式,如果不注明在class中默认为private继承,在struct中默认public继承

四、友元函数、静态成员函数的继承

1.友元函数

在类的学习中,我们都了解了友元,友元可以访问指定类的私有和受保护的自定义成员,如果不是指定的成员,则不能被访问

友元类

(1) 友元函数不是类成员函数,所以不能被继承;
(2) 友元关系是单向的,不具有交换性;
若B类是A类的友元,不一定A类就是B类的友元
(3) 友元关系不能被传递,若B类是A类的友元,C类是B类的友元,C类不一定是A类的友元
友元注意事项

a、友元函数可访问类的私有成员,但不是类的成员函数;
b、友元函数不能用const修饰;
c、友元函数可以在类定义的任何地方声明,不受类访问限定
符限制;
d、一个函数可以是多个类的友元函数;
e、友元函数的调用与普通函数的调用和原理相同;
f、友元关系不能继承,基类的友元对派生类的成员没有特殊的访问权限。如果基类被授予友元关系,则只有基类具有特殊的访问权限。该基类的派生类不能访问授予友元关系的类。

class Base
{
    friend void fun();
public:
    Base(int a = 0, int b = 0, int c = 0)
        : _pub(a)
        , _pro(b)
        , _pri(c)
    {}
    int _pub = 1;
protected:
    int _pro = 2;
private:
    int _pri = 3;
};
class Derive :public Base
{};
int main()
{
    Derive d1;
    d1.fun();
    return 0;
}

这里写图片描述

fun函数不是派生类的成员函数,说明friend函数不能被继承

2.静态成员

class Person
{
public:
    Person(){ ++_count; }
protected:
    string _name; // 姓名
public:
    static int _count; // 统计人的个数。
};
int Person::_count = 0;
class Student : public Person
{
protected:
    int _stuNum; // 学号
};
class Graduate :public Student
{
protected:
    string _seminarCourse; // 研究科目
};
void TestPerson1()
{
    Student s1;
    Student s2; 
    Student s3;
    Graduate s4;
    cout << "人数:" << Person::_count << endl;
    Student::_count = 0;
    cout << "人数:" << Person::_count << endl;
}
int main()
{
    TestPerson1();
    return 0;
}

这里写图片描述

在这段代码和结果中。我们可以看到的是_count是可以被继承下来的,并且在整个继承体系中static成员只有一个,无论有多少个派生类,都只仅仅有一个static成员;

  • 11
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值