c++ ----继承

C++为什么要有继承

 我们都知道很多类都有自己的数据成员以及函数,在编写程序时,会有很多类的拥有相同的数据成员和函数,为了节省时间以及代码量,我们把这些公共的数据和函数封装成一个类,后面的类只要继承这个类即可。

什么是继承

 继承是面向对象复用的重要手段。继承是类型之间的关系建模,共享公有的东西,实现各自本质不同的东西。当创建一个类时,您不需要重新编写新的数据成员和成员函数,只需指定新建的类继承了一个已有的类的成员即可。这个已有的类称为基类,新建的类称为派生类。
例如:

这里写图片描述

  • 1.继承方式和访问限定符的关系
    继承的访问限定符有:
     public / protected /private
    这里写图片描述

  • 三种继承关系下基类成员的在派生类的访问关系变化

这里写图片描述

  1. 基类的私有成员在派生类中不能被访问,如果一些基类成员不想被基类帝乡访问,但需要在派生类中访问,就定义为保护成员,可以看出保护成员限定符是因继承才出现的。
  2. public继承是一个接口继承,保持is-a原则,每个父类可用的成员对子类也可用,因为每个子类对象也都是一个父类对象。
  3. protected/private继承是一个实现继承,基类的部分成员并未完全成为子类接口的一部分,是has-a的关系原则,所以非特殊情况下不会使用这两种继承关系,在绝大多数的场景下使用的都是公有继承。
  4. 不管是哪种继承方式,在派生类内部都可以访问基类的公共成员和保护成员,但基类的私有成员存在但是不能访问。
  5. 使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public,不过最好显示的写出继承方式。
  6. 在实际运用中一般使用public继承,极少场景下使用protected/private继承。

继承与转换(public继承)

  • 子类对象可以赋值给父类对象(切割/切片)
    这里写图片描述

  • 父类对象不能赋值给子类对象。

  • 父类的指针或引用可以只想子类对象。
  • 子类对象的指针或引用不能指向父类对象
class person
{
public:
    void fun()
    {

    }
protected:
    string _name;
};

class teacher:public person
{
public:
    int _age;
};

int main()
{
    person p;
    teacher t;

    p = t;  //子类对象可以赋值给父类对象。
    //t=p;不允许

    person *p1 = &t;  //父类的指针或引用可以指向子类对象
    person &q1 = t;

    teacher *p2 = (teacher*)&p; //子类的引用或指针不能指向父类对象,(可以强转类型之后完成)
    teacher& q2 = (teacher&)p;
}

  • 在继承体系中基类和派生类都有独立的作用域。

  • 隐藏(重定义):子类和父类中有同名成员,子类成员将屏蔽父类对成员的直接访问(在子类成员函数中,可以使用 基类::基类成员 访问)

派生了默认成员函数

 在继承关系里面,在派生类中如果没有显示定义六个默认成员函数,编译系统则会默认合成这六个成员函数。

当基类构造函数需要外部传递参数才能进行初始化时,派生类必须显式定义构造函数,为基类传递参数;基类如果不需要传递或者可以不传递参数,派生类可以不用显式定义构造函数。

lass person
{
public:
    person(const char* name)  //基类构造函数
        :_name(name)
    {}
    person(const person& p)  //基类拷贝构造
        :_name(p._name)
    {}
    person& operator=(const person& p)  //赋值运算符重载
    {
        if (this != &p)
        {
            _name = p._name;
        }
        return *this;
    }
    ~person()               //基类析构
    {}

protected:
    const char* _name;
};

class student :public person
{
public:
    student(const char* name, int num)   //派生类构造函数
        :person(name)
        , _num(num)
    {}
    student(const student& s)  //派生类拷贝构造
        :person(s)
        , _num(s._num)
    {}

    student & operator=(const student& s) //派生类赋值运算符重载
    {
        if (this != &s)
        {
            person::operator=(s);
            _num = s._num;
        }
        return *this;
    }
    ~student()    //派生类析构
    {}

protected:
    int _num;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值