C++面向对象基础:访问权限、三种继承权限详解

引言

继承是面向对象中十分重要的一个概念,通过继承可以对很多有某种共性的事物进行抽象。许多课程中介绍继承,都会用父子关系来叙述几个类之间的关系,但这种描述并不能很好解释继承的真谛。基类的设计,应该是对具某类事物属性与方法的抽象;子类继承自基类,应当继承的是基类的基本功能,并且应该要有自己独特的属于与方法。两者直接是一种派生关系,在模仿的基础上有自己的特点,而不是单纯的属于关系。有一种动物叫做骡子,驴与马结合所生,骡子既不是马也不是驴,但它结合了两者的很多特点。

继承权限与访问权限

内部访问与外部访问

内部访问:在类内部定义类函数等操作,访问类的属性或者方法叫做内部访问。
外部访问:在类的外部,比如创建了一个类实例对象,通过点.操作符或者->操作符来访问类数据或方法,叫做外部访问。

弄清这两个东西后,我们接着讲解两种权限。

访问权限

在C++中,继承权限与访问权限一样,都有三种:public、protected、private。
在三种访问权限(不牵扯到继承与友元)中,声明为public的属性与方法,内部与外部均可访问到;proteced与private只能在其内部访问。按照保护程度来排序,应为:private>protected>public
代码测试:
基类的定义

class Human{
    
    
public:
    Human(){
    
    
        name = "无名";
        gender = "男";
        age = 0;
    }
    Human(const string&name,const string&gender,int age):name(name),gender(gender),age(age){
    
    }
    string name;
    int getAge(){
    
    return this->age;}
    string getGender(){
    
    return this->gender;}
protected:
    string gender;
private:
    int age;
};

测试函数:

void testHuman()
{
    
    
    Human h1;
    //通过 . 运算符只能获取到name 但获取不到gender 
    //h1.gender ;报错 在类外部访问proteced成员 
    //h1.age;//报错 相当于在类外部访问private成员
    
    cout<<"h1的信息"<<h1.name<<" "<<h1.getAge()<<"岁 性别"<<h1.getGender()<<endl;
}

由此可见,在单纯的访问时,上面三种权限的说明是正确的,只有public权限才能在类外部访问,其它两种均只能在类内部访问。

继承权限

不管是哪种继承权限,都可以说将父类中的属性与方法再改访问权限放入到子类中,有一点需要注意的是,protected权限,除了在基类内部访问以外,还能在其子类中访问。
此处先分别通过三个测试案例来进行讲解。

public继承

子类定义:

class Man:public Human{
    
    
    public:
        Man():Human(){
    
    }
        Man(const string&name,const string&gender,int age):Human(name,gender,age){
    
    }
        string getName(){
    
    return this->name;}
        // 在子类内部 可以访问基类的protected权限的属性与方法
        string getGender(){
    
    return this->gender;}
        // 报错 age不可访问 父类的private 是只能父类在类内部才能直接访问
        // 类外部 即便是子类也不能直接访问 但可通过父类的getAge来间接访问
        //int getAge(){return this->age;}
};  

测试代码:

void testPublicInherit()
{
    
    
    Man m1;
    //可以访问原来的public权限的属性与方法
    cout<<m1.name<<"\t"<<m1.getAge()<<endl;
    //尝试在类外部访问protected和private
    //m1.gender; 报错 . 不出来这个属性
    //m1.age; 报错 . 不出来这个属性
}

由此可见,public继承时,基类中的public与protected权限的属性、方法,在子类中权限并不会被改变,但对于基类private的,可以理解为它在哪定义为private的,就只有在哪个类内部才能直接访问。

protected继承

子类定义:

class Woman:protected Human{
    
    
    public:
        Woman():Human(){
    
    }
        Woman(const string&name,const string&gender,int age):Human(name,gender,age){
    
    }
        //在子类中 基类protected权限的可以直接访问
        string getname(){
    
    return this->name;}
        string getgender(){
    
    return this->gender;}
        //报错 相当于在Human外部直接访问age 可以通过getAge函数间接访问
        //string getage(){return this->age;}
        int getage(){
    
    return Human().getAge();}
};

测试代码:

void testProtectedInherit()
{
    
    
    Woman w1;
    //尝试访问原来public权限的属性与方法
    //cout<<w1.name<<endl;报错 能 . 出来这个属性 但显示不可访问
    //cout<<w1.getAge()<<"\t"<<w1.getGender()<<"\t"<<w1.getName()<<endl; 报错 能 . 出来这个属性 但显示不可访问
    //可见 protected继承后 基类中public权限的属性与方法 不再是public
    //通过自己的函数 来间接访问
    //gender、name在子类定义的函数中可以直接访问 那么gender、name的权限为protected
    cout<<w1.getage()<<"\t"<<w1.getgender()<<"\t"<<w1.getname()<<endl;
}

至于为什么gender、name在子类中的权限为protected,可以通过再次public继承Woman类来测试,子类定义:

class Girl:public Woman{
    
    
    public:
        Girl():Woman(){
    
    }
        Girl(const string&name,const string&gender,int age):Woman(name,gender,age){
    
    }
        //测试是否能直接访问Woman类中的name和gender
        void test(){
    
     cout<<this->name<<"\t"<<this->gender<<endl;}
};

测试代码:

	Girl g1;
    //测试是否能直接访问
    //cout<<g1.name<<endl;报错 不可访问 排除public
    //在内部函数可以直接访问不报错 因此在基类Woman中 name gender必定不为private
    g1.test();

private继承

子类定义:

class Hemophrodite:private Human{
    
    
    public:
        Hemophrodite():Human(){
    
    }
        Hemophrodite(const string&name,const string&gender,int age):Human(name,gender,age){
    
    }
        //内部能直接访问 基类访问权限为public与protected的属性方法
        string getgender(){
    
    return this->gender;}
        string getname(){
    
    return this->name;}
        //尝试能否直接访问 private
        //int getage(){return this->age;} 不可访问 
};

测试代码:

void testPrivateInherit()
{
    
    
    Hemophrodite hp;
    //尝试直接访问基类的属性
    //cout<<hp.name<<hp.gender<<hp.age<<endl;不可访问
    //尝试访问基类的方法
    //cout<<hp.getAge()<<hp.getGender()<<hp.getName()<<endl;不可访问
    //尝试通过自身定义的函数来访问 不报错
    cout<<hp.getgender()<<hp.getname()<<endl;
}

相信通过代码与注释,各位读者应该有了一些猜想,在此总结一下:
在继承时,若继承权限的保护程度高于访问权限,那么继承权限会将访问权限覆盖,比如private继承时,基类中public与protected的权限,在子类中均为private访问权限;若低于或者相等,则不变。需要注意的是,继承并不是将属性与方法改一下权限然后全扔到子类里面,而是还加上了父类的访问权限,如父类的private属性方法,是只能在父类内部访问的,无论以何种继承,是无法在子类中直接访问的(但可间接访问)。
最后举三个例子
public继承:购物广场对于人们而言,是所有人都能进去玩耍的,大部分地方相当于public访问权限,但里面有些地方普通人进不去,只能工作人员进去,相当于protected访问权限,而有些地方只能商场老板使用,相当于private访问权限。
protected继承:有些餐馆只对内部VIP开放,即相当于只能子类才能访问,但VIP也不能访问所有地方。
private继承:房屋是私有财产,只有有限的几个家人才能访问,家人能使用客厅、卫生间,但一般不能访问家人的隐私。

猜你喜欢

转载自blog.csdn.net/weixin_45416439/article/details/126212454