首页 > 其他分享 >UVM - 2 (补充虚基类及纯虚函数知识点)

UVM - 2 (补充虚基类及纯虚函数知识点)

时间:2024-03-13 16:33:05浏览次数:25  
标签:知识点 函数 int void 继承 纯虚 基类 public

虚方法和纯虚方法

虚方法

  • 定义一个函数为虚函数,不代表函数为不被实现的函数。
  • 定义他为虚函数是为了允许用基类的指针来调用子类的这个函数。
virtual function

纯虚方法

  • 定义一个函数为纯虚函数,才代表函数没有被实现。
  • 定义纯虚函数是为了实现一个接口,起到一个规范的作用,规范继承这个类的程序员必须实现这个函数。
pure virtual function

虚继承及虚基类详解

多继承(Multiple Inheritance)是指从多个直接基类中产生派生类的能力,多继承的派生类继承了所有父类的成员。尽管概念上非常简单,但是多个基类的相互交织可能会带来错综复杂的设计问题,命名冲突就是不可回避的一个。

多继承时很容易产生命名冲突,即使我们很小心地将所有类中的成员变量和成员函数都命名为不同的名字,命名冲突依然有可能发生,比如典型的是菱形继承,如下图所示:

类 A 派生出类 B 和类 C,类 D 继承自类 B 和类 C,这个时候类 A 中的成员变量和成员函数继承到类 D 中变成了两份,一份来自 A-->B-->D 这条路径,另一份来自 A-->C-->D 这条路径。

在一个派生类中保留间接基类的多份同名成员,虽然可以在不同的成员变量中分别存放不同的数据,但大多数情况下这是多余的:因为保留多份成员变量不仅占用较多的存储空间,还容易产生命名冲突。假如类 A 有一个成员变量 a,那么在类 D 中直接访问 a 就会产生歧义,编译器不知道它究竟来自 A -->B-->D 这条路径,还是来自 A-->C-->D 这条路径。下面是菱形继承的具体实现:

//间接基类A
class A{
protected:
    int m_a;
};

//直接基类B
class B: public A{
protected:
    int m_b;
};

//直接基类C
class C: public A{
protected:
    int m_c;
};

//派生类D
class D: public B, public C{
public:
    void seta(int a){ m_a = a; }  //命名冲突
    void setb(int b){ m_b = b; }  //正确
    void setc(int c){ m_c = c; }  //正确
    void setd(int d){ m_d = d; }  //正确
private:
    int m_d;
};

int main(){
    D d;
    return 0;
}

这段代码实现了上图所示的菱形继承,第 25 行代码试图直接访问成员变量 m_a,结果发生了错误,因为类 B 和类 C 中都有成员变量 m_a(从 A 类继承而来),编译器不知道选用哪一个,所以产生了歧义。

为了消除歧义,我们可以在 m_a 的前面指明它具体来自哪个类:

void seta(int a){ B::m_a = a; }

这样表示使用 B 类的 m_a。当然也可以使用 C 类的:

void seta(int a){ C::m_a = a; }

虚继承

为了解决多继承时的命名冲突和冗余数据问题,C++ 提出了虚继承,使得在派生类中只保留一份间接基类的成员。
在继承方式前面加上 virtual关键字就是虚继承,请看下面的例子:

//间接基类A
class A{
protected:
    int m_a;
};

//直接基类B
class B: virtual public A{  //虚继承
protected:
    int m_b;
};

//直接基类C
class C: virtual public A{  //虚继承
protected:
    int m_c;
};

//派生类D
class D: public B, public C{
public:
    void seta(int a){ m_a = a; }  //正确
    void setb(int b){ m_b = b; }  //正确
    void setc(int c){ m_c = c; }  //正确
    void setd(int d){ m_d = d; }  //正确
private:
    int m_d;
};

int main(){
    D d;
    return 0;
}

这段代码使用虚继承重新实现了上图所示的菱形继承,这样在派生类 D 中就只保留了一份成员变量 m_a,直接访问就不会再有歧义了。

虚继承的目的是让某个类做出声明,承诺愿意共享它的基类。其中,这个被共享的基类就称为虚基类(Virtual Base Class),本例中的 A 就是一个虚基类。在这种机制下,不论虚基类在继承体系中出现了多少次,在派生类中都只包含一份虚基类的成员。

现在让我们重新梳理一下本例的继承关系,如下图所示:

标签:知识点,函数,int,void,继承,纯虚,基类,public
From: https://www.cnblogs.com/Icer-newer/p/18070348

相关文章

  • 【Linux进程的知识点】
    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录前言操作系统的知识补充我们来理解一个用户操作接口:进程的理解进程的基本概念描述进程-PCBtask_struct-PCB的一种task_struct内容分类进程的task_struct本身内部的属性有哪些?1、启动查找pid......
  • 商票琐碎知识点记录
    1.基础交易关系:直接前手可以基于没有基础关系进行抗辩【票据司法解释第二条  依照票据法第十条的规定,票据债务人(即出票人)以在票据未转让时的基础关系违法、双方不具有真实的交易关系和债权债务关系、持票人应付对价而未付对价为由,要求返还票据而提起诉讼的,人民法院应当依法受理......
  • C语言最重要的知识点(2)
    第二章第一节:数据输出(一)(二)1、使用printf和scanf函数时,要在最前面加上#include“stdio.h”2、printf可以只有一个参数,也可以有两个参数。(选择题考过一次)3、printf(“第一部分”,第二部分 );把第二部分的变量、表达式、常量以第一部分的形式展现出来!4、printf(“a=%d,b=%d”,12......
  • 机器学习知识点
    目录机器学习的概念:样本:特征:标签:回归和分类任务:泛化能力:假设空间:输出空间:有监督学习:无监督学习:半监督学习:奥卡姆剃刀:四个损失函数:正确率:误差:过拟合:过拟合的处理:欠拟合欠拟合的处理方式:没有免费的午餐定理(NFL定理):误差训练误差:测试误差:验证误差:泛化误差......
  • 两个视图基类 LL
    1、APIViewrest_framework.views.APIView APIView是RESTframework提供的所有视图的基类,继承自Django的View父类。APIView与View的不同之处在于:传入到视图方法中的是RESTframework的Request对象,而不是Django的HttpRequeset对象;视图方法可以返回RESTframework的Respons......
  • Django基础知识点一
    Django基础知识点【零】补充方法【1】Django项目测试if__name__=='__main__':importosimportdjangoos.environ.setdefault('DJANGO_SETTINGS_MODULE','BookSystem.settings')django.setup()'''测试代码''......
  • 计算机三级知识点(信息安全技术)
    计算机三级(信息安全技术)知识点源于顺文好友的馈赠TCSES(橘皮书)将计算机系统的安全划分为四个等级七个级别,是计算机安全评估的第一个正式标准。香农发表《保密系统的通信理论》1977年美国制定数据加密标准DES,为加密算法标准化奠定了基础。1994年美国颁布数字签名标准DS......
  • Spring 知识点
    SpringSpring是什么?Spring为了解决企业级应用的复杂性而创建,简化开发。如下简化:基于POJO的轻量级和最小侵入性编程;以IoC(控制反转)、DI(依赖注入)和面向接口实现松耦合;基于AOP(切面编程)和惯性进行声明式编程;以切面和模版减少样式代码;SpringIoC(控制反转)IoC负责创建、......
  • 知识点
    案例:Collection集合存储学生对象并遍历需求:创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合。分析:(1)定义学生类(2)创建Collection集合对象(3)创建学生对象(4)把学生添加到集合(5)遍历集合(迭代器方式)完整代码:packagecom.xuexi;importjava.util.ArrayList;impo......
  • 计算机网络知识点
    两种交换方式分组(packet)交换不长期占用链路,将报文分组,所有分组由路由器按照目的地址丢到网络中,也就是用户不需要发送/接收分组时就不占用网络资源。电路(circuit)交换通信双方建立一条专用链路,不进行分组交换时这条链路也不能给别人用。路由器与交换机路由器(圆)工作在网络层(......