C++多态之继承5-继承和访问说明符(public ,protected, private)

本文详细介绍了C++中继承时访问说明符public, protected, private的作用,探讨了不同继承方式(public, private, protected)如何影响成员的访问权限。重点讲述了派生类对基类成员的访问规则以及外部访问的限制。" 126521659,14548659,物联网:塑造未来的关键力量,"['物联网技术', '智能城市', '人工智能应用', '医疗物联网', '自动驾驶技术']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

之前关于继承的文章,我们总是将类的数据成员设置为公有的(public),这么做只是为了使例子更简单易懂。本文中,我们将讨论在继承的过程中,访问说明符所扮演的角色,同时也会讲到C++中的不同种类的继承。

关于这点,之前我们已经看过私有(private)和公有(public)访问说明符,这些说明符能够决定谁能访问类的成员。简单会议下,公有成员能在任何地方被访问。私有成员只能被同一个类的成员函数访问。请注意这意味着派生类不能访问基类的私有成员

class Base
{
private:
    int m_nPrivate; // can only be accessed by Base member functions (not derived classes)
public:
    int m_nPublic; // can be accessed by anybody
};
当处理继承类时,事情变得有点复杂了。

首先,有第三种访问说明符:protected。请仔细看下面的代码:

class Base
{
public:
    int m_nPublic; // can be accessed by anybody
private:
    int m_nPrivate; // can only be accessed by Base member functions (but not derived classes)
protected:
    int m_nProtected; // can be accessed by Base member functions, or derived classes.
};
 
class Derived: public Base
{
public:
    Derived()
    {
        // Derived's access to Base members is not influenced by the type of inheritance used,
        // so the following is always true:
 
        m_nPublic = 1; // allowed: can access public base members from derived class
        m_nPrivate = 2; // not allowed: can not access private base members from derived class
        m_nProtected = 3; // allowed: can access protected base members from derived class
    }
};
 
int main()
{
    Base cBase;
    cBase.m_nPublic = 1; // allowed: can access public members from outside class
    cBase.m_nPrivate = 2; // not allowed: can not access private members from outside class
    cBase.m_nProtected = 3; // not allowed: can not access protected members from outside class
}
第二点,当一个派生类继承于基类时,访问说明符可能会因为继承方式而改变。因为有3中继承方式:public,private,protected。

// Inherit from Base publicly
class Pub: public Base
{
};
 
// Inherit from Base privately
class Pri: private Base
{
};
 
// Inherit from Base protectedly
class Pro: protected Base
{
};
 
class Def: Base // Defaults to private inheritance
{
};
如果你不指定一种继承方式,那么C++默认指定为private继承。

这给了我们9种组合:3中成员访问说明符(public,private,protected),3中继承方式(public,private,protected)。

下面我将尽力解释它们之间的区别,不过在开始之前,我们的脑子里应该明白:有三种方法来访问成员

1.一个类总是能访问它自己的成员,不管访问说明符是什么。

2.公有访问类的成员要看类的访问说明符。

3.一个派生类访问从基类那继承来的成员要看基类的访问说明符。

通过下面的实例,我想大家能更加明白。


Public 继承

公有继承是使用的最广泛的继承方式。事实上,很少使用其他方式的继承,所有我们首要的任务就是理解这种继承方式。当公有继承一个基类,基类所有的成员将维持它们原有的访问说明符。私有成员还是私有,公有成员还是公有,受保护的成员还是受保护。

class Base
{
public:
    int m_nPublic;
private:
    int m_nPrivate;
protected:
    int m_nProtected;
};
 
class Pub: public Base
{
    // Public inheritance means:
    // m_nPublic stays public
    // m_nPrivate stays private
    // m_nProtected stays protected
 
    Pub()
    {
        // The derived class always uses the immediate parent's class access specifications
        // Thus, Pub uses Base's access specifiers
        m_nPublic = 1; // okay: anybody can access public members
        m_nPrivate = 2; // not okay: derived classes can't access private members in the base class!
        m_nProtected = 3; // okay: derived classes can access protected members
    }
};
 
int main()
{
    // Outside access uses the access specifiers of the class being accessed.
    // In this case, the access specifiers of cPub.  Because Pub has inherited publicly from Base,
    // no access specifiers have been changed.
    Pub cPub; 
    cPub.m_nPublic = 1; // okay: anybody can access public members
    cPub.m_nPrivate = 2; // not okay: can not access private members from outside class
    cPub.m_nProtected = 3; // not okay: can not access protected members from outside class
}
上面的例子很直观,我们可以从中发现4点:

1.派生类不能直接访问基类的私有成员。

2.受保护的访问说明符允许派生类直接访问基类的受保护成员,但是不允许在外部对其访问。

3.派生类使用从基类继承的访问说明符。

4.外部使用派生类的访问说明符。

总结下,如下表:

Public inheritance
Base access specifier Derived access specifier Derived class access? Public access?
Public Public Yes Yes
Private Private No No
Protected Protected Yes No

Private继承

私有继承:所有从基类继承来的成员都是私有的,这意味着私有成员依然是私有的,同时受保护和公有成员也变成了私有的。

需要特别注意的是这并不影响派生类对基类成员的访问(在派生类里对基类的成员访问不受影响)。它仅仅是影响了通过派生类来访问这些成员(从外部访问)。

下面的例子能很好说明这点:

class Base
{
public:
    int m_nPublic;
private:
    int m_nPrivate;
protected:
    int m_nProtected;
};
 
class Pri: private Base
{
    // Private inheritance means:
    // m_nPublic becomes private
    // m_nPrivate stays private
    // m_nProtected becomes private
 
    Pri()
    {
        // The derived class always uses the immediate parent's class access specifications
        // Thus, Pub uses Base's access specifiers
        m_nPublic = 1; // okay: anybody can access public members
        m_nPrivate = 2; // not okay: derived classes can't access private members in the base class!
        m_nProtected = 3; // okay: derived classes can access protected members
    }
};
 
int main()
{
    // Outside access uses the access specifiers of the class being accessed.
    // Note that because Pri has inherited privately from Base,
    // all members of Base have become private when access through Pri.
    Pri cPri;
    cPri.m_nPublic = 1; // not okay: m_nPublic is now a private member when accessed through Pri
    cPri.m_nPrivate = 2; // not okay: can not access private members from outside class
    cPri.m_nProtected = 3; // not okay: m_nProtected is now a private member when accessed through Pri
 
    // However, we can still access Base members as normal through Base:
    Base cBase;
    cBase.m_nPublic = 1; // okay, m_nPublic is public
    cBase.m_nPrivate = 2; // not okay, m_nPrivate is private
    cBase.m_nProtected = 3; // not okay, m_nProtected is protected
}
总结如下表:

Private inheritance
Base access specifier Derived access specifier Derived class access? Public access?
Public Private Yes No
Private Private No No
Protected Private Yes No

Protected继承

这种继承方式几乎很少被使用,只存在于特殊情况。受保护继承:公有和受保护成员变成了受保护的,私有成员依然是私有。

这里我们就不举例子了,稍微更改下上面的例子就能很好的验证。

Protected inheritance
Base access specifier Derived access specifier Derived class access? Public access?
Public Protected Yes No
Private Private No No
Protected Protected Yes No

总结

关于访问说明符,继承方式以及派生类的相互影响会引发了很多的疑惑,这里做更近一步的阐明:

首先,基类设置访问说明符,基类总是能访问自己的成员,这些访问说明符只影响派生类或者外部是否能访问基类的成员。

其次,派生类访问基类的成员只受基类对成员所设置的访问说明符限制,并不受继承方式的影响,也就是说不管是公有继承,私有继承还是受保护继承,派生类总能访问基类的公有和受保护成员,总是无法访问基类的私有成员,上面的例子能很好说明这点

最后,派生类能通过继承方式来改变从基类继承来的成员的访问方式,这并不影响派生类自己的成员,仅仅影响外部派生类的派生类对这些成员的访问(派生类的派生类)

最后再给一个例子:

class Base
{
public:
    int m_nPublic;
private:
    int m_nPrivate;
protected:
    int m_nProtected;
};
基类可以无限制的访问自己的成员m_nPublic,m_nPrivate,m_nProtected,但是外部只能外放m_nPublic。它的派生类可以访问m_nPublic和m_nProtected。

class D2: private Base
{
public:
    int m_nPublic2;
private:
    int m_nPrivate2;
protected:
    int m_nProtected2;
}
D2可以无限制的访问自己的成员m_nPublic2, m_nPrivate2, m_nProtected2,它也可以访问基类的m_nPublic和m_nProtected,但无法访问m_nPrivate。由于是私有继承,所以外部无法通过D2对象来访问任何基类的成员,D2的派生类也无法访问Base的任何成员。

class D3: public D2
{
public:
    int m_nPublic3;
private:
    int m_nPrivate3;
protected:
    int m_nProtected3;
};
D3能无限制访问自己的成员,D3可以访问D2的m_nPublic2和m_nProtected,但不能访问D2的m_nPrivates,D3也不能访问任何Base的成员。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值