C++之继承

继承

继承定义

格式:

class 父类{};

class 子类:继承方式 父类名{
//新增子类数据
 };

其中继承方式有:private protected public(推荐)

**public:**可以被任意实体访问

**protected:**只允许子类及本类的成员函数访问

**private:**只允许本类的成员函数访问

在这里插入图片描述

公共继承 保持不变,保护继承变保护,私有继承变私有,所有父类私有在子类中不可见。

class Person{
public:
    int a;
protected:
    int b;
private:
    int c;
};

class Son:public Person{
    
public:
//在子类的成员函数中,protected是可以访问的
    void fun(){
        cout<<a<<b;//正常访问
        cout<<c;// error c不可访问
    }
};

int main()
{
    Son ob;//子类的对象
    cout<<ob.a<<endl;
    cout<<ob.b<<endl;//b是protected,不可通过对象访问

    return 0;
}
class Person{
protected:
    int a;
};


int main()
{
    Person p;
    p.a=8;//error protected只允许本类或子类的成员函数访问
    return 0;
}

子类的构造析构顺序

#include <iostream>

using namespace std;

class Person{
public:
    Person(){
        cout<<"父类构造函数"<<endl;
    }
    ~Person(){
        cout<<"父类析构函数"<<endl;
    }

};

class Other{
public:
    Other(){
        cout<<"成员对象构造函数"<<endl;
    }
    ~Other(){
        cout<<"成员对象析构函数"<<endl;
    }
};



class Son:public Person{
public:
    Other ob;

public:

    Son(){
        cout<<"子类构造函数"<<endl;
    }
    ~Son(){
        cout<<"子类析构函数"<<endl;
    }
};


int main()
{
    Son ob;

    return 0;
}

打印结果:

父类构造函数
成员对象构造函数
子类构造函数
子类析构函数
成员对象析构函数
父类析构函数

在这里插入图片描述

子类调用成员对象和父类的有参构造

  • 子类 会自动调用成员对象、父类的默认构造

  • 子类 必须使用初始化列表调用成员对象、父类的有参构造。

初始化列表时:父类写类名称 成员对象用对象名。

#include <iostream>

using namespace std;

class Person{
public:
    int a;
public:


    Person(){
        cout<<"父类构造函数"<<endl;
    }
    Person(int a){
        this->a=a;
        cout<<"父类的有参构造"<<endl;
    }
    ~Person(){
        cout<<"父类析构函数"<<endl;
    }

};

class Other{
public:
    int  b;

public:
    Other(){
        cout<<"成员对象构造函数"<<endl;
    }
    Other(int b){
        this->b=b;
        cout<<"成员对象的有参构造"<<endl;
    }
    ~Other(){
        cout<<"成员对象析构函数"<<endl;
    }
};



class Son:public Person{
public:
    Other ob;
    int c;

public:

    Son(){
        cout<<"子类构造函数"<<endl;
    }
    Son(int  a,int b,int c):Person(a),ob(b){
        //this->a=a;//注意:这样只会先调用父类的无参构造后进行赋值
        this->c=c;
        cout<<"子类的有参构造"<<endl;
    }
    ~Son(){
        cout<<"子类析构函数"<<endl;
    }
};


int main()
{
    Son ob(10,20,30);

    return 0;
}

父类的有参构造
成员对象的有参构造
子类的有参构造
子类析构函数
成员对象析构函数
父类析构函数

子类和父类同名成员处理

同名成员 最简单 最安全的处理方式:加作用域

1、子类和父类 同名成员数据

子类默认优先访问 子类的同名成员
必须加父类作用域 访问父类的同名成员

class Person{
public:
    int a;//同名a
public:
    Person(int a){
        this->a=a;
    }

};



class Son:public Person{
public:
    int a;

public:
    Son(int  a,int b):Person(a){
        this->a=b;
    }
};


int main()
{
    Son ob(100,200);
    cout<<ob.a<<endl;//优先访问子类中的a
    cout<<ob.Person::a<<endl;//想访问父类中的a,只能带上作用域
    return 0;
}

2、子类和父类同名成员函数

重载:无继承,同一作用域,参数的个数、顺序、类型不同都可重载
重定义:有继承,子类 重定义父类的同名函数(参数可以不同)(非虚函数)

子类一旦重定义了父类的同名函数(不管参数是否一致),子类中都将屏蔽父类所有的同名函数。

#include <iostream>

using namespace std;

class Person{
public:

    void fun(){
        cout<<"Person的fun()"<<endl;
    }


};

class Son:public Person{
public:
    void fun(){
        cout<<"Son类的fun()"<<endl;
    }
    void fun(int a){
        cout<<"Son类的fun(int)"<<a<<endl;
    }

};


int main()
{
    Son ob;
    ob.fun();//默认调用Son中的fun
    ob.fun(10);
    ob.Person::fun();//使用父类中fun

    return 0;
}

子类不能继承父类的成员

父类的构造、析够、operator= 不能被子类 继承

多继承

1、多继承的格式

 class 父类1{};
 class 父类2{};

 class 子类:继承方式1 父类1, 继承方式2 父类2
 {
 //新增子类数据
 };

子类就拥有了父类1,父类2的大部分数据

2、多继承中的同名函数

#include <iostream>

using namespace std;

class Person1{
public:
    int a;
    Person1(int a):a(a){}
};

class Person2{
public:
    int a;
    Person2(int a):a(a){}
};

class Son:public Person1,public Person2{
public:
    int a;
    Son(int a,int b,int c):Person1(a),Person2(b),a(c){};
};
int main()
{
    Son ob(1,2,3);
    cout<<ob.a<<endl;//3
    cout<<ob.Person1::a<<endl;//1
    cout<<ob.Person2::a<<endl;//2
    return 0;
}

菱形继承

菱形继承:有公共祖先的继承 叫菱形继承。
最底层的子类 数据 会包含多分(公共祖先的数据)

在这里插入图片描述

#include <iostream>

using namespace std;
class People{
public:
    int age;

};

class Person1:  public People{

};

class Person2:  public People{

};

class Son:public Person1,public Person2{

};
int main()
{
    Son ob;
    //cout << ob.age << endl;//二义性
    cout<< ob.Person1::age<<endl;
     cout<< ob.Person2::age<<endl;
    return 0;
}

怎么才能只要公共祖先的一份数据呢?

在继承方式 前加virtual修饰,子类虚继承父类 子类只会保存一份公共数据。

#include <iostream>

using namespace std;
class People{
public:
    int age;

};

class Person1:virtual  public People{

};

class Person2: virtual public People{

};

class Son:public Person1,public Person2{

};
int main()
{
    Son ob;
    cout<<ob.age<<endl;
    return 0;
}

在这里插入图片描述

虚继承 会在子类中产生 虚基类指针(vbptr) 指向 虚基类表(vbtable), 虚基类表纪录的是通过该指针访问公共祖先的数据的偏移量

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值