当前课程知识点:C++语言程序设计进阶 >  第七章 继承与派生 >  派生类成员的标识与访问 >  访问从基类继承的成员

返回《C++语言程序设计进阶》慕课在线视频课程列表

访问从基类继承的成员在线视频

访问从基类继承的成员

访问从基类继承的成员

作用域限定

当派生类与基类中有相同成员时:

例7-6 多继承同名隐藏举例

#include <iostream>
using namespace std;
class Base1 {   
public:
    int var;
    void fun() { cout << "Member of Base1" << endl; }
};
class Base2 {   
public:
    int var;
    void fun() { cout << "Member of Base2" << endl; }
};
class Derived: public Base1, public Base2 {
public:
    int var;    
    void fun() { cout << "Member of Derived" << endl; }
};

int main() {
    Derived d;
    Derived *p = &d;

  //访问Derived类成员
    d.var = 1;
    d.fun();    

    //访问Base1基类成员
    d.Base1::var = 2;
    d.Base1::fun(); 

    //访问Base2基类成员
    p->Base2::var = 3;
    p->Base2::fun();    

    return 0;
}

二义性问题

二义性问题举例

class A {
public:
    void  f();
};
class B {
public:
    void f();
    void g()
};
class C: public A, piblic B {
public:
    void g();
    void h();
};
如果定义:C  c1;
则 c1.f() 具有二义性
而 c1.g() 无二义性(同名隐藏)
例7-7  多继承时的二义性和冗余问题
//7_7.cpp
#include <iostream>
using namespace std;
class Base0 {   //定义基类Base0
public:
    int var0;
    void fun0() { cout << "Member of Base0" << endl; }
};
class Base1: public Base0 { //定义派生类Base1 
public: //新增外部接口
    int var1;
};
class Base2: public Base0 { //定义派生类Base2 
public: //新增外部接口
    int var2;
};

例7-7  多继承时的二义性和冗余问题
class Derived: public Base1, public Base2 {
public: 
    int var;
    void fun() 
  { cout << "Member of Derived" << endl; }
};

int main() {    //程序主函数
    Derived d;
    d.Base1::var0 = 2;
    d.Base1::fun0();
    d.Base2::var0 = 3;
    d.Base2::fun0();
    return 0;
}

Derived类对象d的存储结构示意图


下一节:虚基类

返回《C++语言程序设计进阶》慕课在线视频列表

访问从基类继承的成员课程教案、知识点、字幕

大家好

欢迎回来继续学习

C++语言程序设计

这一节呢

我们来考虑这样一个问题

基类的成员

继承到派生类中以后

访问的时候

有没有什么

特殊需要注意的问题呢

会不会出现一些二异性

或者无法访问的情况呢

我们知道

如果说

你写着派生类里面的成员

有于基类中成员相同的时候

就会有一些麻烦了

当我们写派生类的时候

如果在派生类中定义了

与基类中的成员同名的成员

会怎么样呢

在这种情况下

如果不加特别地限定

那么通过派生类对象

使用的就是派生类中

自己新定义的同名成员

那么如果

一定要通过派生类的对象

去访问那些从基类继承过来的

又被隐藏的同名成员

该怎么办呢

也是有办法的

这个时候呢

就要使用基类名

和作用域限定符来限定

在下面的例子中呢

我们会看到

派生类中的同名成员呢

就隐藏了从基类继承过来的成员

在这里呢

我们在基类Base1类中定义了

变量var和函数fun

在另一个基类Base2里面

也定义了同名的变量和函数

接下来呢

Derived类继承了Base1

继承了Base2

同时它自己也定义了

同名的变量和函数

现在我们来看

在主函数中

我们定义一个Derived类的对象

通过对象名去调用函数的时候

比如调用函数fun

它到底访问的是谁

现在我们通过单步跟踪

观察一下

现在即将要调用这个fun函数

我们按f11

看到进到这个Derived对象

自己所属类的fun函数中了

为什么呢

因为在Derived类里面

定义了同名的函数

那它就屏蔽从基类

或者说隐藏了从基类

继承过来的函数了

那么这样

如果依然要访问

从基类继承过来的数据成员

和函数成员

怎么办呢

那么这里的办法就是

通过基类名限定来访问

那我们再跟踪到

这个fun函数里面去

进到基类1的fun函数里面了

同样呢

如果你用指针去访问

也是一样的

比如说我们将这个Derived指针

Derived地址

这个指针p

用来访问对象

那么访问的肯定是

Derived对象了

但是我们刻意要调用

它从Base2继承过来的这个函数

怎么调用

通过类名限定

就进到Base2的fun函数里面了

当我们的派生类

从不同的基类继承的时候呢

如果这些不同的基类中

有同名的成员

那么这些成员

继承到派生类中以后

如何区分它们呢

如何访问它们呢

那这个时候呢

当然访问肯定就存在了二异性

你不能直接用对象名

或者引用名.成员名

或者是说派生类指针指向成员名

这样的方式访问了

那要解决这个二异性呢

当然有简单的办法

就是用类名来限定

那么我们看这个例子中呢

我们在类a中定义了函数f

在类b中也定义了函数f

那么在类b中定义了函数g

在派生类c里面也定义了函数g

C以公有方式继承a 继承b

C类自己还新定义了

一个自己的函数h

这个时候

如果我们定义了C1类的对象c1

我们用c1.f的方式来调用函数f

就具有二异性了

因为它有两个函数f

是一个是从a类继承来的

一个是从b类继承来的

如果调用c1.g就没有二异性

因为根据同名隐藏规则

在C类中定义了函数g

那么直接调用的

就是C类自己的函数g

那么我们一定要调用函数f

怎么办呢

可以用类名来限定

这是一种办法

另一种办法就是说

我们在C类中

可以自己再定义一个函数f

在这个C类的函数f里面

根据需要去选择调用A f

或者是B f

这两种办法都是可以的

那这是这个关于多继承的时候

有可能发生二异性

和冗余问题的例题

在这我们定义一个Base0类

它里面定义了变量var0 fun0

然后Base1类继承了Base0

Base2类也继承了Base0

接下来

我们让Derived类继承Base1

和Base2

现在 Derived类里面

到底有些什么成员呢

我们来看这个示意图

实际上这个继承关系

相当于是这样的

Base1继承Base0

Base2也继承Base0

然后Derived继承Base1 Base2

那我们看这个示意图

这个示意图

实际上在Derivd类的对象里面

它就包含着

从Base0继承来的成员

包含了两次

为什么呢

因为Derived类

它有两个直接基类

所以它会包含

从Base1继承来的成员

和从Base2继承来的成员

但是Base1的成员里面

就包含了从Base0继承的成员

Base2的成员

也包含了

从Base0继承的成员

所以呢

Base0里面定义的数据成员

就在Derived类里面

出现了两份

那么当然这个时候

如果你按这样d.var0访问

就就二异性了

所以我们就要用类名来限定

我们是通过对象d

访问从Base1

继承来的var0 fun0

还是访问

从Base2继承来的var0 fun0

这样来做呢

虽然这个二异性的问题解决了

没有二异性了

但是我们看

对象的存储

它的对象成员的存储

它是冗余的

冗余第一个问题

是会带来空间的浪费

第二个问题

是会带来不一致性

使用的时候会发生一些混淆

如果这两个本改是一回事的成员

被分别置与了不同的值

那这个结果又如何解释呢

结果就没什么意义了

所以这种情况呢

通过这个例题看到

有可能发生二异性

和冗余的情况

其实是我们写程序

应该避免的

C++语言程序设计进阶课程列表:

第七章 继承与派生

-导学

--导学

-继承的基本概念和语法

--继承的基本概念和语法

-第七章 继承与派生--继承的基本概念和语法习题

-继承方式

--继承方式简介及公有继承

--私有继承和保护继承

-第七章 继承与派生--继承方式

-基类与派生类类型转换

--基类与派生类类型转换

-第七章 继承与派生--基类与派生类类型转换

-派生类的构造和析构

--派生类的构造函数

--派生类的构造函数举例

--派生类的复制构造函数

--派生类的析构函数

--第七章 继承与派生--派生类的构造和析构

-派生类成员的标识与访问

--访问从基类继承的成员

--虚基类

-第七章 继承与派生--派生类成员的标识与访问

-小结

--小结

-综合实例

--第七章综合实例

-实验七

--实验七

-第七章讲义

第八章 多态性

-导学

--导学

-第八章 多态性--导学

-运算符重载

--运算符重载的规则

--双目运算符重载为成员函数

--单目运算符重载为成员函数

--运算符重载为非成员函数

-第八章 多态性--运算符重载

-虚函数

--虚函数

--虚析构函数

--虚表与动态绑定

-第八章 多态性--虚函数

-抽象类

--抽象类

--第八章 多态性--抽象类

-override与final

--override与final

-第八章 多态性--override与final

-小结

--第八章小结

-综合实例

--第八章综合实例

-实验八

--实验八

- 第八章讲义

第九章 模板与群体数据

-导学

--导学

-模板

--函数模板

--类模板

-第九章 模板与群体数据--模板

-线性群体

--线性群体的概念

-第九章 模板与群体数据--线性群体

-数组

--数组类模板

--例9-4数组类应用举例

-链表

--链表的概念与结点类模板

--链表类模板

-第九章 模板与群体数据--链表

-栈

--栈类模板

--栈类模板课后习题

--例9-9 栈的应用

--例9-9 栈的应用课后习题

-队列

--队列类模板

-第九章 模板与群体数据--队列

-排序

--排序概述

--插入排序

--选择排序

--交换排序

-第九章 模板与群体数据--排序

-查找

--查找

--查找课后习题

-小结

--小结

-综合实例

--综合实例

-实验九

--实验九

- 第九章讲义

第十章 泛型程序设计与C++标准模板库

-导学

--导学

-泛型程序设计及STL的结构

--泛型程序设计的基本概念

--STL简介

-第十章 泛型程序设计与C++标准模板库--泛型程序设计及STL的结构

-迭代器

--迭代器

-第十章 泛型程序设计与C++标准模板库--迭代器

-容器的基本功能与分类

--容器的基本功能与分类

-第十章 泛型程序设计与C++标准模板库--容器的基本功能与分类

-顺序容器

--顺序容器的基本功能

--顺序容器的特征

--顺序容器的插入迭代器与适配器

--第十章 泛型程序设计与C++标准模板库--顺序容器

-关联容器

--关联容器分类和基本功能

--集合

--映射

--多重集合和多重映射

-第十章 泛型程序设计与C++标准模板库--关联容器

-函数对象

--函数对象

--函数适配器

-算法

--算法

-小结

--第十章小结

-综合实例

--综合实例

-实验十

--实验十

- 第十章讲义

第十一章 流类库与输入/输出

-导学

--导学

-I/O流的概念及流类库结构

--I/O流的概念及流类库结构

-第十一章 流类库与输入/输出--I/O流的概念及流类库结构

-输出流

--输出流概述

--向文本文件输出

--向二进制文件输出

--向字符串输出

-第十一章 流类库与输入/输出--输出流

-输入流

--输入流概述

--输入流应用举例

--从字符串输入

-第十一章 流类库与输入/输出--输入流

-输入/输出流

--输入/输出流

-第十一章 流类库与输入/输出--输入/输出流

-小结

--小结

-综合实例

--综合实例

-实验十一

--实验十一

- 第十一章讲义

第十二章 异常处理

-导学

--第12章导学

-异常处理的思想与程序实现

--异常处理的思想与程序实现

-第十二章 异常处理--异常处理的思想与程序实现

-异常处理中的构造与析构

--异常处理中的构造与析构

-第十二章 异常处理--异常处理中的构造与析构

-标准程序库异常处理

--标准程序库异常处理

-第十二章 异常处理--标准程序库异常处理

-小结

--第12章小结

-综合实例

--综合实例

-实验十二

--实验十二

- 第十二章讲义

访问从基类继承的成员笔记与讨论

也许你还感兴趣的课程:

© 柠檬大学-慕课导航 课程版权归原始院校所有,
本网站仅通过互联网进行慕课课程索引,不提供在线课程学习和视频,请同学们点击报名到课程提供网站进行学习。