接口与虚函数的数据结构知识

在了解接口和虚函数的知识前,先整理一下虚函数和接口的定义和作用
接口的作用:

1、接口可以使项目分离,所有层都面向接口开发,提高开发效率;2、接口使代码和代码之间的耦合度降低;3、接口可以多实现,多继承,并且一个类除了接口之外,还可以继承其它类。

虚函数的作用:

用专业术语来解释就是实现多态性(Polymorphism),多态性是将接口与实现进行分离;用形象的语言来解释就是实现以共同的方法,但因个体差异,而采用不同的策略。

这样笼统的看可能比较难懂,先理解一下就好接下来以我自己的学习来记录一下。
接口的概念: 关键字是interface,按照惯例接口的名字以大写字母”I“开头 接口的定义: 是一组包含了函数方法的数据结构,通过这组数据结构、客户代码可以调用组件对象的功能;且可以继承多个接口。默认为public但不能写上去

接口只声明属性、方法和事件,成员的定义则是派生类的责任,接口提供了派生类应遵循的标准结构。 接口本身并不实现任何功能,它只是和声明实现的该接口的对象订立一个必须实现哪些行为的契约;

这就相当于接口只是统一了口径,具体怎么做在哪做做多少那都是继承接口的派生类自己去定义完成的了。

而接口中的方法在派生类中如何继承和重写呢,这就涉及到虚函数的知识来,刚刚的定义中也说了,多态性是将接口与现实进行分离。虚函数体现的多态性也就自然跟接口也挂钩了

虚函数体现了面向对象的多态性,虚函数的作用是通过同名的虚函数来使得根据不同的类对象,来调相应的函数实现相应的功能,且会优先调用同名的该类对象的虚函数(即当前类名调用的虚函数,则优先调用该类的虚函数,而不会调用基类或者派生类的同名虚函数);

public class classBase
    {
    
    
        public virtual void Func()
        {
    
    
            Console.WriteLine("This is classBase");
        }
    }

    public class newClass1 : classBase
    {
    
    
        public override void Func()
        {
    
    
            Console.WriteLine("This is newClass1");
        }
    }
    public class newClass2 : classBase
    {
    
    
        public override void Func()
        {
    
    
            Console.WriteLine("This is newClass2");
        }
    }
    public class start
    {
    
    
        public void main()
        {
    
    
            classBase base = new classBase();
            base.Func();
            newclass1 class1 = new newclass1();
            class1.Func();
            newclass2 class2 = new newclass2();
            class2.Func();
        }
    }
   ---------------
   This is classBase
   This is newClass1
   This is newClass2
   ----------------重写后的虚函数也只是调用了该类自身的虚函数

纯虚函数没有函数体只有函数声明,存在纯虚函数则不能生成类对象为抽象类,抽象类是为了统一管理子类对象用于当作父类来生成子类用 。这一点跟接口的定义很类似,所以在接口内的纯虚函数都有派生类来重写实现不同的功能。

继承抽象类时,必须要求实现抽象属性和方法; 实例化抽象类和派生类

派生类:直接用派生类声明和构造     ClassSon b = new ClassSon();
抽象父类:用抽象类声明,用派生类构造  ClassDad a = new ClassSon();

类是一个模板,抽象类是不完整的模板自然而然就不可以使用不完整的模板构造对象。

抽象类的概念:

抽象类不能实例化,可以包含普通函数(属性)和抽象函数(属性),
而且他们必须是共有的public;抽象函数只有函数定义但没有函数体,抽象函数本身也是虚拟(virtual)的;并且含有抽象属性和方法的就一定是抽象类

抽象类的作用:当我们写基类的时候,有的属性方法是一定要被重写的,在基类中实现没有意义,这时候把这个需要实现的属性方法写作抽象类型,这样我们在写派生类的时候直接对没有实现的抽象属性方法进行重写(override)。 且派生类必须对基类所有的抽象类型重写,否则还是抽象类。

接下来就是虚函数的内存原理了—虚函数表
虚函数表是虚函数的载体,它的内存在类对象的首地址,虚函数从虚函数表上开辟。
虚函数表:定义:虚表内存放的是虚函数的地址,但并非函数的真实地址,是call指令的跳转地址
本质:虚函数表的本质是一个数据结构,是一个链表数组,里面存放着虚函数的地址,数组的最后一个元素为0
虚函数对比普通函数是会多开辟4个字节空间,因为它多开辟了一个虚函数表
在这里插入图片描述

虚函数的作用:当调用一个虚函数时,大多数编译器通过虚函数表和虚函数表指针实现,当一个类声明了虚函数或者继承了虚函数,这个类就会有自己的虚函数表,也就是一个函数指针数组。有的编译器是链表,不过方法
都是差不多的。虚函数表数组中每一个元素对应一个函数指针、指向该类的虚函数,同时该类的每一个对象都会包含虚函数表指针,虚函数表指针指向虚函数表的地址;
每个声明了虚函数或者继承了虚函数的类都会有一个自己的虚函数表;该类的每个对象都会包含一个虚函数表指针指向虚函数表;
虚函数按照其生命顺序放置虚函数表中,虚函数表数组中的每个元素对应一个函数指针指向该类的虚函数。

猜你喜欢

转载自blog.csdn.net/weixin_50746193/article/details/124555182