C++基础教程面向对象(学习笔记(47))

继承和访问说明符

在本章前面的课程中,您已经了解了基本继承的工作原理。在我们到目前为止的所有示例中,我们都使用了公共继承。也就是说,我们的派生类公开继承基类。

在本课中,我们将详细介绍公共继承,以及另外两种继承(私有和受保护)。我们还将探索不同类型的继承如何与访问说明符交互以允许或限制对成员的访问。

到目前为止,您已经看到了私有和公共访问说明符,它们决定了谁可以访问类的成员。作为一个快速复习,公共成员可以被任何人访问。私有成员员只能通过同一个类或友元函数能访问。这意味着派生类不能直接访问基类的私有成员!

class Base
{
private:
    int m_private; // 只能由Base成员和友元函数访问(不是派生类)
public:
    int m_public; // 可以被任何人访问
};

这非常简单,你现在应该已经习惯了。

受保护的访问说明符

处理继承的类时,事情会变得复杂一些。

C ++有一个我们尚未讨论的第三个访问说明符,因为它仅在继承上下文中有用。该保护的访问说明符允许成员所属的,友元函数和派生类访问成员的类。但是,受保护的成员无法从类外访问。

class Base
{
public:
    int m_public; // 可以被任何人访问
private:
    int m_private; // 只能由Base成员和友元函数访问(但不能派生类)
protected:
    int m_protected; // c可以由Base成员,有元函数和派生类访问
};
 
class Derived: public Base
{
public:
    Derived()
    {
        m_public = 1; //allowed:可以从派生类访问公共Base成员
        m_private = 2; // not allowed: 无法从派生类访问私有Base成员
        m_protected = 3; // allowed: 可以从派生类访问受保护的Base成员
    }
};
 
int main()
{
    Base base;
    base.m_public = 1; // allowed: 可以从外部类访问公共成员
    base.m_private = 2; // not allowed: 无法从外部类访问私有成员
    base.m_protected = 3; // not allowed: 无法从外部类访问受保护的成员
}

在上面的示例中,您可以看到受保护的基本成员m_protected可以由派生类直接访问,但不能由公共访问。

那我什么时候应该使用受保护的访问说明符?

使用基类中的受保护属性,派生类可以直接访问该成员。这意味着如果您稍后更改了有关该受保护属性的任何内容(类型,值的含义等等),您可能需要更改基类和所有派生类。

因此,当您(或您的团队)将是从您自己的类派生的那些时,使用受保护的访问说明符是最有用的,并且派生类的数量是合理的。这样,如果您对基类的实现进行了更改,并且因此需要对派生类进行更新,那么您可以自己进行更新(并且不需要永久更新,因为派生类的数量有限)。

使您的成员私有可以为您提供更好的封装,并将派生类与基类的更改隔离开来。但是,构建公共或受保护的接口以支持公共和/或派生类所需的所有访问方法或功能也是成本。这是额外的工作,可能不值得,除非你期望别人是你的类派生的,或者你有大量的派生类,其中更新它们的成本将是昂贵的。

不同种类的继承,以及它们对访问的影响

首先,类有三种不同的方式从其他类继承:public,private和protected。

为此,只需在选择要继承的类时指定所需的访问类型:

// 公共继承Base
class Pub: public Base
{
};
 
// 私有从Base继承
class Pri: private Base
{
};
 
// 保护地从Base继承
class Pro: protected Base
{
};
 
class Def: Base // 默认为私有继承
{
};

如果您不选择继承类型,C ++默认为私有继承(如果您没有另外指定,就像成员默认为私有访问一样)。

这为我们提供了9种组合:3种成员访问说明符(公共,私有和受保护),以及3种继承类型(公共,私有和受保护)。

那么这些之间的区别是什么?简而言之,当继承成员时,可以更改继承成员的访问说明符(仅在派生类中),具体取决于所使用的继承类型。换句话说,在基类中公共或受保护的成员可以更改派生类中的访问说明符。

这看起来有点令人困惑,但并不是那么糟糕。我们将花费本课程的其余部分详细探讨这一点。

在我们逐步完成示例时,请记住以下规则:

#类总是可以访问自己的(非继承的)成员。
#公共访问基于其正在访问的类的访问说明符的类的成员。
#类根据从父类继承的访问说明符访问继承的成员。这取决于访问说明符和使用的继承类型。

公共继承

公共继承是迄今为止最常用的继承类型。事实上,您很少会看到或使用其他类型的继承,因此您的主要关注点应该是理解本节。幸运的是,公共继承也是最容易理解的。当您公开继承基类时,继承的公共成员保持公开,并且继承的受保护成员保持受保护。并且无法访问的继承私有成员无法访问。

基类中的访问说明符 公开继承时的访问说明符

基类中的访问说明符公共继承时的访问说明符
public公共访问
private无法访问
protected受保护

这是一个展示工作原理的例子:

class Base
{
public:
    int m_public;
private:
    int m_private;
protected:
    int m_protected;
};
 
class Pub: public Base // 注意:公共继承
{
    // 公共继承意味着:
    // 公共继承成员保持公开(所以m_public被视为公共)
    //受保护的继承成员保持受保护(因此m_protected被视为受保护)
    //私有继承的成员无法访问(因此m_private无法访问)
public:
    Pub()
    {
        m_public = 1; // okay:m_public被继承为公共的
        m_private = 2; // not okay: m_private无法从派生类中访问
        m_protected = 3; // okay:m_protected继承为protected
    }
};
 
int main()
{
    // 外部访问使用正在访问的类的访问说明符。
    Base base;
    base.m_public = 1; // okay: m_public在Base是公开的
    base.m_private = 2; // not okay: m_private在Base中是私有的
    base.m_protected = 3; // not okay: m_protected在Base中受到保护
 
    Pub pub;
    pub.m_public = 1; // okay: m_public在Pub是公开的
    pub.m_private = 2; // not okay: m_private在Pub不能访问
    pub.m_protected = 3; // not okay: m_protected在Pub中受到保护

}

这与上面我们引入受保护的访问说明符的示例相同,只是我们已经实例化了派生类,只是为了表明在公共继承中,事物在基类和派生类中的工作方式相同。

公共继承是你应该使用的,除非你有特殊的理由不这样做。

规则:除非您有特殊原因,否则请使用公共继承。

私有继承

使用私有继承,基类中的所有成员都将作为私有继承。这意味着私有成员保持私密,受保护的公共成员变得私密。

请注意,这不会影响派生类访问从其父级继承的成员的方式!它只影响试图通过派生类访问这些成员的代码。

class Base
{
public:
    int m_public;
private:
    int m_private;
protected:
    int m_protected;
};
 
class Pri: private Base // 注意:私有继承
{
    // 私有继承意味着:
    // 公共继承成员变为私有(因此m_public被视为私有)
    // 受保护的继承成员变为私有(因此m_protected被视为私有)
    //私有继承的成员无法访问(因此m_private无法访问)
public:
    Pri()
    {
        m_public = 1; // okay: m_public现在在Pri中是私有的
        m_private = 2; // not okay: 派生类无法访问基类中的私有成员
        m_protected = 3; // okay:m_protected现在在Pri中是私有的
    }
};
 
int main()
{
    // 外部访问使用正在访问的类的访问说明符。
    //在这种情况下,base的访问说明符。
    Base base;
    base.m_public = 1; // okay: m_public在Base是公开的
    base.m_private = 2; // not okay: m_private在Base中是私有的
    base.m_protected = 3; // not okay: m_protected在Base中受到保护
 
    Pri pri;
    pri.m_public = 1; // not okay: m_public在 Pri是私有的
    pri.m_private = 2; // not okay: Pri中无法访问m_private
    pri.m_protected = 3; // not okay: m_protected在Pri是私有的

}
以表格形式总结:

基类中的访问说明符 私有继承时的访问说明符

基类中的访问说明符私有继承时的访问说明符
public私有的
private无法访问
protected私有的

当派生类与基类没有明显关系,但在内部使用基类进行实现时,私有继承会很有用。在这种情况下,我们可能不希望基类的公共接口通过派生类的对象公开(就像我们公开继承的那样)。

实际上,很少使用私有继承。

受保护的继承

受保护的继承是最后一种继承方法。它几乎从未使用过,除非在非常特殊的情况下。通过受保护的继承,公共成员和受保护成员将受到保护,私有成员将无法访问。

因为这种形式的继承是如此罕见,我们将跳过这个例子,并用表格总结:

基类中的访问说明符 受保护地继承时的访问说明符

基类中的访问说明符受保护继承时的访问说明符
public受保护
private无法访问
protected受保护

最后一个例子

class Base
{
public:
	int m_public;
private:
	int m_private;
protected:
	int m_protected;
};

Base可以不受限制地访问自己的成员。公众只能访问m_public。派生类可以访问m_public和m_protected。

class D2 : private Base // 注意: 私有继承
{
	// 私有继承意味着:
	// 公共继承成员变得私有
	// 受保护的继承成员变为私有成员
	// 私有继承的成员无法访问
public:
	int m_public2;
private:
	int m_private2;
protected:
	int m_protected2;
};

D2可以不受限制地访问自己的成员。D2可以访问Base的m_public和m_protected成员,但不能访问m_private。由于D2私有地继承了Base,因此当通过D2访问时,m_public和m_protected现在被视为私有。这意味着公共在使用D2对象时不能访问这些变量,也不能从D2派生任何类。

class D3 : public D2
{
	// 公共继承意味着:
	// 公共继承成员保持公开
	// 受保护的继承成员依然受保护
	// 私有继承的成员无法访问
public:
	int m_public3;
private:
	int m_private3;
protected:
	int m_protected3;
};

D3可以不受限制地访问自己的成员。D3可以访问D2的m_public2和m_protected2成员,但不能访问m_private2。由于D3公开继承了D2,因此m_public2和m_protected2在通过D3访问时保留其访问说明符。D3无法访问Base的m_private,它在Base中已经是私有的。它也无法访问Base的m_protected或m_public,当D2继承它们时,它们都变成了私有的。

Summary:

访问说明符,继承类型和派生类交互的方式会导致很多混乱。我尽可能地尝试澄清事情:

首先,类(和友元)总是可以访问自己的非继承成员。访问说明符仅影响外部和派生类是否可以访问这些成员。

其次,当派生类继承成员时,这些成员可以更改派生类中的访问说明符。这不会影响派生类自己的(非继承的)成员(具有自己的访问说明符)。它只会影响派生类派生的外部和类是否可以访问这些继承的成员。

这是一个包含所有访问说明符和继承类型组合的表:

基类中的访问说明符 公开继承时的访问说明符 私有继承时的访问说明符 受保护地继承时的访问说明符

基类中的访问说明符公共继承时的访问说明符私有继承时的访问说明符受保护地继承时的访问说明符
public公共私有的受保护
private无法访问无法访问无法访问
protected受保护私有的受保护

最后请注意,尽管在上面的示例中,我们仅显示了使用成员变量的示例,但这些访问规则适用于所有成员(例如,在类中声明的成员函数和类型)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值