C++复习(2)派生类成员的标志与访问
来源:互联网 发布:mac 显卡驱动 编辑:程序博客网 时间:2024/05/17 18:13
首先,在派生类中,成员按照访问属性可以分为以下四类:
(1)不可访问成员;这些成员是通过继承得到的,比如继承的基类中原有的私有成员。
(2)私有成员;
(3)保护成员;
(4)公有成员。
如果这些成员中,有相同的名字的话该怎么办呢?比如我们继承的基类中有个成员名叫做test,在我们的派生类中也有个成员名字叫做test,那该怎么区分它们呢?这就是本文主要探讨的问题。
1、作用域分辨符
在类的派生的层次结构中,基类和派生类的成员都有各自的类作用域,两者的关系是:基类的作用域在外层,派生类的类作用域在里层
如果派生类声明了一个和基类中名字相同的变量,那么派生类的新成员则会隐藏基类中的同名成员,直接使用对象或者指针只能访问到派生类中的新成员。这是对于成员变量来说,那么对于成员函数呢?如果派生类中声明了一个和基类中名字相同的函数,即使函数的参数表不同,也会隐藏基类中所有函数名为该名称的重载形式。(这是因为只有在相同的作用域中定义的函数才可以重载,派生类和基类的同名函数在不同的作用域内,因此不能重载)
那这种情况下如何访问原有的基类中的同名变量和函数呢,可以通过作用域分辨符来访问。具体看如下代码:
#include <iostream>using namespace std;class Base1//基类1{public:int var;void fun(){cout<<"Base1 var = "<<var<<endl;}};class Base2//基类2{public:int var;void fun(){cout<<"Base2 var = "<<var<<endl;}};class Derived:public Base1,public Base2//派生类{public:int var;void fun(){cout<<"Derived var = "<<var<<endl;}};int main(){Derived d;d.var = 3;d.fun();d.Base1::var = 1;d.Base1::fun();d.Base2::var = 2;d.Base2::fun();return 0;}
可以看出我们上面说的是对的。当然了,其实这样做的目的就是为了不产生语义的二义性,用其他方法也可以代替,例如
using Base1::var;using Base2::fun;这种情况下默认的使用的就是Base1中的var变量,Base2中的fun()函数了。
但是还有一个问题,我们上面的两个基类Base1和Base2都是没有基类的,那如果他们有共同的基类,派生类该如何访问他们基类的基类的成员呢?
看如下代码:
#include <iostream>using namespace std;class Base0{public:int var0;void fun(){cout<<"Base0 var = "<<var0<<endl;}};class Base1:public Base0//基类1{public:int var;};class Base2:public Base0//基类2{public:int var;};class Derived:public Base1,public Base2//派生类{public:int var;};int main(){Derived d;d.Base1::var0 = 1;d.Base1::fun();d.Base2::var0 = 2;d.Base2::fun();return 0;}
运行结果如下:
其实这个时候,派生类对象d的内存中存了5个数据,分别为Base1::var0,Base1::var,Base2::var0,Base2::var,Derived::var,存放了两份成员函数Base1::fun(),Base2::fun()。
这是因为如果派生类的部分或者全部直接基类是从另一个共同的基类派生而来,在这些直接基类中,从上一级基类继承来的成员就拥有相同的名称,因此派生类中也有产生同名的现象,对于这种类型的同名成员也要使用作用域分辨符作为唯一标识,而且必须使用直接基类来进行限定。
这时如果我们使用
d.Base0::var = 1;d.Base0::fun();就会出错,原因是语义不明,也就是编译器不知道现在用的这一份是从Base1中来的,还是从Base2中来的。
就像我们上面说的,如果派生类的若干直接基类有共同基类的话,派生类对象中会存放多份直接基类的共同基类中的成员副本,这样会比较占用内存,那么如何解决这个问题呢,就是我们接下来要讲得虚基类了。
2、虚基类
class 派生类:virtual 继承方式 基类这种情况下,基类就变成虚基类了。这样在基类的多个派生类的同一派生类对象中,对于该基类的数据成员副本只有一份,同时函数也就只有一个映射。
#include <iostream>using namespace std;class Base0{public:int var;void fun(){cout << "Base0 var = " << var << endl;}};class Base1 :virtual public Base0{public:int var1;void fun1(){cout << "Base1 var1 = " << var1 << endl;}};class Base2 :virtual public Base0{public:int var2;void fun2(){cout << "Base2 var2 = " << var2 << endl;}};class Derived :public Base1, public Base2{int vard;};int main(){Derived test;test.var = 5;test.fun();}可以看到这种代码编译是不会有问题的,运行结果如下:
- C++复习(2)派生类成员的标志与访问
- 派生类成员的标识与访问
- 派生类成员的访问
- 派生类成员的访问
- C++派生类的成员标识与访问
- C++派生类的成员标识与访问
- 派生类与派生类对象对基类成员的访问
- 继承与派生:派生类对基类成员的访问控制之公有继承
- 三十七、继承与派生:派生类对基类成员的访问控制之公有继承
- 派生类成员的访问属性
- 继承与派生:派生类对基类成员的访问控制之保护继承与私有继承
- 三十八、继承与派生:派生类对基类成员的访问控制之保护继承与私有继承
- c++模板类派生:派生类访问基类中的public 和protected成员的一些问题
- 派生类成员对基类的访问
- 基类和派生类的成员访问
- 派生类可以访问基类的private成员吗
- C++派生类对象访问基类的protected成员
- 基类和派生类的成员访问
- 聊聊Android图像格式类及图像转换方法
- 学习态度
- 人见人爱A^B(HDU2035)
- 51nod 最长回文子串 V2(Manacher算法)
- 单片机--ds1302
- C++复习(2)派生类成员的标志与访问
- 文件输入/输出
- Android开发项目经验
- 为什么Java中1000==1000为false而100==100为true?
- 大时代势不可挡,隔行扫描已经消失。BT.709色彩空间也开始离我们远去
- 单片机之利用按键来使数码管上两位示数增加
- 如何学习基于ARM平台的嵌入式系统
- python的&众不同之处(2)
- 第三周项目2--建设“顺序表”的算法库