一、继承的基本概念

        继承使得C++能够从已有的类派生出新的类,而派生类继承了原有类的特征,包括方法。被继承者称为父类或基类,继承者称为子类或派生类。

继承的目的:

  1. 实现代码的重用性
  2. 建立父类和子类之间的联系
  3. 在实现多态的时候,需要通过继承,实现子类对父类函数的重写

继承的格式:

class 类名:继承方式 类名
{
    子类的拓展;
}

 继承的方式:

        public 公有继承、protected 保护继承、private 私有继承

示例:

#include <iostream>
using namespace std;

//封装 人  类  父类/基类
class Person
{
private:
    string name;
    int age;
public:
    //无参构造函数
    Person()
    {
        cout << "父类的无参构造函数" << endl;
    }

    //有参构造
    Person(string name, int age):name(name),age(age)
    {
        cout << "父类的有参构造函数" << endl;
    }
};

//封装 学生 类   共有继承人 类
class Stu:public Person   //子类 、派生类
{
private:
    int id;
    int math;
public:
    //无参构造函数
    Stu()
    {
        cout << "子类的无参构造函数" << endl;
    }

    //有参构造函数
    Stu(string name, int age, int id, int math):Person(name,age),id(id),math(math)
    {
        cout << "子类的有参构造函数" << endl;
    }
    
};

int main()
{
    Stu s("zhangsan",12,1001,78);
    return 0;
}

二、继承中的特殊成员函数

构造函数:

        父类的初始化必须赶在子类之前,换句话说,先调用父类的构造函数,再调用子类的构造函数。

析构函数:

        析构函数调用的顺序:先调用子类的析构函数,再调用父类的析构函数。

先构造的 后析构。 后构造的先析构。

拷贝构造函数:

        父类的拷贝构造函数会继承到子类中,在子类的拷贝构造函数中使用父类的拷贝构造函数,来完成子类从父类继承下来的成员的拷贝工作。

        如果涉及深拷贝,则需要在子类和父类各自完成深拷贝工作。

拷贝赋值函数:

        父类的拷贝赋值函数会继承到子类中,在子类的拷贝赋值函数中使用父类的拷贝赋值函数,来完成子类从父类继承下来的成员的赋值工作。

        如果涉及深拷贝,则需要在子类和父类各自完成深拷贝工作。

示例:

#include <iostream>
using namespace std;

//封装 人  类  父类/基类
class Person
{
private:
    string name;
protected:
    int age;
public:
    int h;
public:
    //无参构造函数
    Person()
    {
        cout << "父类的无参构造函数" << endl;
    }

    //有参构造
    Person(string name, int age, int h):name(name),age(age),h(h)
    {
        cout << "父类的有参构造函数" << endl;
    }
    //拷贝构造函数
    Person(const Person & other):name(other.name),age(other.age),h(other.h)
    {
        cout << "父类的拷贝构造函数"  << endl;
    }


    //拷贝赋值函数
    Person & operator=(const Person &p)
    {
        name = p.name;
        age = p.age;
        h = p.h;
        cout << "父类的拷贝赋值函数" << endl;
        return  *this;
    }


    void show()
    {
        cout << "父类的show" << endl;
    }
};


//封装 学生 类   公有继承人 类
class Stu:public Person   //子类 、派生类
{
private:
    int id;
    int math;


public:
    //无参构造函数
    Stu()
    {
        cout << "子类的无参构造函数" << endl;
    }


    //有参构造函数
    Stu(string name, int age, int h, int id, int math):Person(name,age,h),id(id),math(math)
    {
        cout << "子类的有参构造函数" << endl;
    }


    //拷贝构造函数
    Stu(const Stu & s):id(s.id),math(s.math),Person(s)
    {
        cout << "子类的拷贝构造函数" << endl;
    }


    //拷贝赋值函数
    Stu & operator=(const Stu & s)
    {
        Person::operator=(s);

        id = s.id;

        math = s.math;

        cout << "子类的拷贝赋值函数" << endl;
        return *this;

    }
    void show()
    {
        cout << "子类的show" << endl;
        cout << h << endl; //通过共有继承,类外、子类可以访问父类共有成员
        cout << age << endl; //通过共有继承,子类可以访问父类保护成员,类外不可以访问
        //cout << name << endl;//通过共有继承,子类不可访问父类私有成员,类外不可以访问
    }


};


int main()
{
    Stu s("zhangsan",12,190,1001,78);

    Stu s2=s;

    Stu s3;
    s3 = s2;

//    s.show();
//    s.Person::show();

    return 0;
}

三、总结

        父类的初始化必须赶在子类之前,换句话说,先调用父类的构造函数,再调用子类的构造函数。

        当父类的函数和子类的函数是同名同类型时,不会报错,原因是作用域不同,如果子类实例化出一个对象,这个对象调用该函数,调用的是子类的函数,如果想调用父类中函数。则需要加上类名和作用域限定符。

09-02 14:11