基类与派生类

2024-03-28 11:32
文章标签 基类 派生类

本文主要是介绍基类与派生类,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

初学C++的时候,很多人都很头疼各种访问标号下基类与派生类的关系,其实,死记硬背肯定不是一个好的办法,要知道它们之间的关系,先要分析一下访问标号是如何产生的:

在没有继承之前,类的只有两类用户:类本身和类的使用者。把类成员通过public和private划分恰好体现了这一分割:类的使用者只能访问类的public部分,它们一般是类的接口;而类成员则既可以访问public又可以访问private部分,private部分是类的具体实现。当有了继承之后,类的使用者多了一类:基类的派生类。派生类通常要访问基类的一些具体实现,而又不希望让一般的用户访问这些实现,所以就要把这些内容放置在一起,用protected标号来说明。从该类的使用者的角度,protected成员是私有的,你不能访问基类对象的保护成员,但是从该类的继承者的角度,protected则是共有的,因为他可以被继承下来供派生类使用。

为了更进一步限制派生类对基类成员的访问权限,C++又通过访问列表中的访问标号来控制。具体的说

1.如果继承方式为public,那么基类中的public成员在派生类总仍为public,基类中的protected仍为protected,基类中的private在派生类中不能被访问。

2.如果继承方式为protected,那么基类中的public成员在派生类中为protected,基类中的protected成员在派生类中为protected,基类的private成员在派生类中不能被访问。

3.如果继承方式为private,那么基类中的public成员在派生类中为private,基类中的protected成员在派生类中为private,基类的private成员在派生类中不可访问。

 总结一下:

 

 基类公有成员基类保护成员基类私有成员
公有继承派生类公有成员派生类保护成员派生类不可访问
保护继承派生类保护乘员派生类保护乘员派生类不可访问
私有继承派生类私有成员派生类私有成员派生类不可访问

 再来看一个例子:

//基类
class Base
{
public:Base(int i = 0):baseVal_public(i),baseVal_protected(i),baseVal_private(i){}int baseVal_public;void printVal(){cout<<baseVal_protected<<endl;cout<<baseVal_private<<endl;};
protected:int baseVal_protected;
private:int baseVal_private;};//派生类
class Derived_public:public Base
{
public:Derived_public(int i = 0):Base(i){}void getVal(){//基类的公有成员在派生类中仍未为公有cout<<baseVal_public<<endl;//基类受保护成员变仍未受保护成员cout<<baseVal_protected<<endl;//基类的私有成员不能被派生类继承//cout<<baseVal_private<<endl;}};class Derived_protected:protected Base
{
public:Derived_protected(int i = 0):Base(i){}void getVal(){//基类的共有成员、受保护成员变为受保护成员cout<<baseVal_public<<endl;cout<<baseVal_protected<<endl;//基类私有成员不能被派生类继承//cout<<baseVal_private<<endl;}};class Derived_private:private Base
{
public:Derived_private(int i = 0):Base(i){}void getVal(){//基类的公有成员、受保护成员变为派生类的私有成员cout<<baseVal_public<<endl;cout<<baseVal_protected<<endl;//基类的私有成员不能被继承//cout<<baseVal_private<<endl;}};
int main()
{Base b;//公有成员可以被用户访问cout<<b.baseVal_public<<endl;//私有成员、受保护成员不能被用户访问//cout<<b.baseVal_private<<endl;//cout<<b.baseVal_protected<<endl;//私有成员、受保护成员可以被类成员访问b.printVal();//公有继承下Derived_public d1;//基类的public成员仍为public,可以访问cout<<d1.baseVal_public<<endl;//私有成员,受保护成员仍为私有、受保护,不能访问//cout<<d1.baseVal_protected<<endl;//cout<<d1.baseVal_private<<endl;d1.getVal();//受保护继承Derived_protected d2;	//基类的public变为派生类的protected//cout<<d2.baseVal_public<<endl;//基类的protected变为派生类的protected//cout<<d2.baseVal_protected<<endl;//基类的private不能被继承//cout<<d2.baseVal_private<<endl;d2.getVal();//私有继承Derived_private d3;//基类的公有成员、受保护成员变为派生类的私有//cout<<d3.baseVal_public<<endl;//cout<<d3.baseVal_protected<<endl;//私有成员不能被继承//cout<<d3.baseVal_private<<endl;d3.getVal();return 0;
}


程序中,注释起来的代码都是会报错的,报错的原因就在这行代码的上面,这里就不做过多解释了。

当然,虽然你通过访问列表中的访问标号进行了限制,但是总是可以通过在派生类中加一个using声明来恢复它的权限(注意,只能恢复,不能提高)

class Derived_private:private Base
{
public:Derived_private(int i = 0):Base(i){}void getVal(){//基类的公有成员、受保护成员变为派生类的私有成员cout<<baseVal_public<<endl;cout<<baseVal_protected<<endl;//基类的私有成员不能被继承//cout<<baseVal_private<<endl;}using Base::baseVal_public1;};

那就可以

	cout<<d3.baseVal_public1<<endl;

还有一点需要注意的,就会友元关系在继承和派生以后会发生什么变化。

总的来说,分为两点:1.如果一个类被授予为另一个类的友元,它的派生类并不不是这个类的友元。2.基类的友元对基类的派生类不起作用。举个例子来说明:

//基类  
class Base  
{  
friend class Frnd;  
public:  Base(int i = 0):baseVal_private(i){}  private:  int baseVal_private;  };  class D1:public Base  
{  
private:  int derivedVal;  };  class Frnd  
{  
public:  int mem(Base b){return b.baseVal_private;}  //基类的友元对派生类来说不起作用  //int mem(D1 d){return d.derivedVal;}  };  class D2:public Frnd  
{  
public:  //友元类的派生类不再是授予有缘的那个类的友元  //int mem(Base b){return b.baseVal_private;}  };

最后有一点需要注意,如果你使用的是class定义的派生类,那么如果不写访问标号,那么默认继承关系为private;如果使用struct定义的派生类,不写访问标号,则默认继承关系为public。


这篇关于基类与派生类的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/855495

相关文章

C++(继承与派生,虚基类,作用域标识符)

类的继承与派生: 继承关系与派生类:      类的继承,是新的类从以后类那里继承已有的特性,从已有类产生新类的过程就是类的派生,新类产生后,就具备了已有类的特征,原有的类叫做基类,产生的新类叫做派生类。 语法形式: class派生类名:继承方式―基类名1,继承方式―基类名2,…,继承方式―基类名n(派生类成员声明;};    一个派生类,可以同时有多个基类,这种情况成为多继承,同理,

穿越Java世界的继承奇旅:从基类到子类的华丽蜕变

1.为什么要继承 2.什么是继承以及继承的方式 3.继承的一些语法 4.父类成员的访问 5.关键字super 6.关键字protected 7.关键字final 8.继承与组合 一:为什么要继承 ①代码重用:继承允许我们重用、扩展或修改父类的属性和方法,而无需重新编写相同的代码。这有助于减少代码冗余,提高代码的可维护性和可扩展性。 ②实现多态:多态是面向对象编程的三大特性之

条款07 为多态基类声明virtual析构函数

总结:         (1)任何带有虚函数的类都几乎确定应该定义一个虚析构函数。一个经验是:只有当类含有至少一个virtual函数才会为它声明virtual析构函数。        (2)如果一个类不含有virtual函数,通常表示它并不意图作为基类;当类不意图作为基类,令其析构函数为virtual是个馊主意。因为有虚函数,该类就要有指向虚函数 表的指针,这样的话,类对象的体积就会增大(

C++笔记之在基类和派生类之间进行类型转换的所有方法

C++笔记之在基类和派生类之间进行类型转换的所有方法 code review! 文章目录 C++笔记之在基类和派生类之间进行类型转换的所有方法1.dynamic_cast和std::static_pointer_cast在基类和派生类之间的转换使用场景下的区别1.1.`dynamic_cast`1.2.`std::static_pointer_cast`1.3.总结 2.dynamic_c

单件基类实现与使用

单件基类实现 template<typename T>class PublicSingleton{protected:PublicSingleton() {}public:static T& getInstance() noexcept(std::is_nothrow_constructible<T>::value){static T instance;return instance;}v

C#下在派生类中引发基类事件的方法与示例

文章目录 基类事件在派生类中的定义及触发方式基类事件的传播机制示例总结 在面向对象编程中,继承是代码复用的一种重要方式。C#作为一种面向对象的编程语言,允许派生类继承基类的属性和方法。基类定义了一系列共有的属性和行为,而派生类则可以在基类的基础上添加新的特性或重写基类的方法。事件作为一种特殊的成员,也可以在基类中被定义,并在派生类中被触发和使用。 基类事件在派生类中

对派生类指针使用C风格的强制类型转换为基类指针

以下来自语言大模型的回答: 值可能发生改变 当对派生类指针使用C风格的强制类型转换成基类指针时,指针的值可能会发生改变。这主要是由于多重继承和虚继承的存在。以下是几个关键点解释: 单继承情况下: 在单继承的情况下,派生类指针转换为基类指针通常不会改变指针的值。基类子对象通常位于派生类对象的开始位置。多重继承情况下: 当涉及多重继承时,派生类可能包含多个基类子对象。这时,指向派生类的指针转换为

模拟原神圣遗物系统-小森设计项目,设计圣遗物词条基类

项目分析 首先需要理解圣遗物的方方面面 比如说圣遗物主词条部分和副词条部分都有那些特点 稍等一会:原神,启动! 在此说明了什么? 这是完全体 :主副 词条都有 如果 升级直接+暴击率 那么就留点 或者是另外的元素充能 这两个词条可稀有啦 我还可以接受哈哈哈 还有 若第一个副词条是暴击伤害直接起飞 真的圣遗物就得是看运气,唉 ,急不来的。原神 是角色养成 圣遗物 虽

C++多重继承,虚基类与友元

一.多重继承 就是一个类继承多个基类; class <派生类名>:<派生方式1><基类名1>,```<派生方式n><基类名n> class Derived:public:Base1,public:Base2 上述形式:基类之间由逗号隔开,且必须指明继承方式,否则默认为私有继承; 1.注意事项: a.各种派生方式对于基类成员在派生类中的访问权限与单继承相同; b.在使用多继承时,对