自学内容网 自学内容网

【C++】继承

继承

面向对象三大特性之一

父类:又叫基类

子类:派生类

语法:

class 子类 : 继承方式 父类

继承的方式

继承方式有三种:pubilc公共继承、protected保护继承、private私有继承

不管哪种继承方式,都无法继承到父类的私有成员

(事实上,子类也有继承到父类的私有成员,只是由编译器隐藏后访问不到,父类的私有成员被继承后,也会占用子类的内存空间)

名称作用范围结果
public公共继承父类的中成员是公共属性的,继承后在子类也是公共属性;父类的中成员是保护属性的,继承后在子类也是保护属性;
protected保护继承父类的中成员是公共属性或保护属性,继承后在子类都是保护属性;
private私有继承父类的中成员是公共属性或保护属性,继承后在子类都是私有属性;

继承的基本使用

class Base{//定义父类     
public:    
    int a; 
};
class Son:pubilc Base{//Son类公共继承Base类     
};
int main(){    
    Son son;//实例化son类    
    son.a = 1;//使用从父类中继承过来的成员属性 
}

//

继承中 先调用父类构造函数,再调用子类构造函数,析构顺序与构造相反

继承存在同名成员

问题:当子类与父类出现同名的成员,如何通过子类对象,访问到子类或父类中同名的数据呢?

访问子类同名成员 直接访问即可

访问父类同名成员 需要加作用域

class Base{//定义父类    
public:
    int a;//子类和父类都有一个a成员属性
    void fun(){
        //子类和父类都有一个fun成员函数    
    }
    void fun(int b){
        //父类fun成员函数重重载   
    }
}
class Son:pubilc Base{//Son类公共继承Base类
public:
    int a;//子类和父类都有一个a成员属性
    void fun(){
        //子类和父类都有一个fun成员函数    
    }
}
int main(){
    Son son;//实例化son类
    son.a = 1;//直接访问的是子类的a
    son.Base::a = 1;//加作用域访问从父类继承的a
    son.fun();//直接访问的是子类的fun()
    son.Base::fun();//加作用域访问从父类继承的fun()
    
    son.fun(10);//子类没有这个函数的用法,报错,并且无法使用父类的重载函数fun(int b)
    //因为当子类和父类有同名函数时,父类的同名函数都会被屏蔽,要访问应加作用域
    son.Base::fun(10);//正确使用父类的重载函数fun(int b)的方法
}

继承存在同名静态成员

问题:继承中同名的静态成员在子类对象上如何进行访问?

静态成员和非静态成员出现同名,处理方式一致

访问子类同名成员 直接访问即可

访问父类同名成员 需要加作用域

本质上时同一块内存,不管修改谁都一样;

class Base{//定义父类    
public:
    static int a;
}

int Base::a = 100;//静态成员属性,类类声明,类外定义

class Son:pubilc Base{//Son类公共继承Base类
public:
    static int a;
}
int main(){
    Son son;//实例化son类
    //静态成员属性有两种访问方法
    //1.通过对象访问
    son.a = 1;//使用son对象自己的a
    son.Base::a = 1;//使用从父类中继承过来的a
    
    //2.通过类访问
    Son::a = 1;//使用Son类访问a
    Son::Base::a = 1;//使用Son类作用下的Base类访问a
}

多继承语法

一个类允许继承多个类,也就是说子类可以有多个父类

语法:

class 子类 :继承方式 父类1 , 继承方式 父类2...

多继承可能会引发父类中有同名成员出现,需要加作用域区分

class Base1{//定义父类1    
public:
    int a;
}
class Base2{//定义父类2  
public:
    int a;
}
class Son:pubilc Base1,pubilc Base2{//Son类公共继承Base类
public:
        int a;
}
int main(){
    Son son;//实例化son类
    son.a = 1;//使用自己的成员属性a
    son.Baes1::a = 1;//使用从父类Baes1中继承过来的成员属性a
    son.Baes2::a = 1;//使用从父类Baes2中继承过来的成员属性a
}

菱形继承

就假设类B1和B2都继承了A类,此时C类同时继承 B1和B2,这种情况就是菱形继承,又叫钻石继承

菱形继承会出现继承多个重复的数据,比如说,类B1和B2都继承了A类的num成员属性,C类同时继承 B1和B2,就会出现既有B1的num,又有B2的num,事实上C只需要用到一份num

处理方法:

继承前加virtual关键字后,变为虚继承

class A{
public:
    int num;    
}
class Base1: virtual public A{//定义父类1  
public:
    int a;
}
class Base2::virtual public A{//定义父类2    
public:
    int a;
}
class Son:pubilc Base1,pubilc Base2{//Son类公共继承Base类
    
}

这样当Son同时继承Base1和Base2时,虚继承Base1的a和Base2的a会被指向同一片内存


原文地址:https://blog.csdn.net/GFH358/article/details/140247190

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!