Virtual
 
声明虚拟方法

语法

Type typename Extends base_typename
End Type

说明

虚拟方法是可以被从它们声明的类型派生的数据类型覆盖的方法,允许多态。与Abstract方法相反,虚拟方法必须具有一个实现,当虚拟不被覆盖时使用。

派生类型可以通过声明具有相同标识符和签名的方法,意味着相同的参数数量和类型,相同的返回类型(如果有)和相同的调用约定,可以覆盖在其基本类型中声明的虚拟方法:
    • 如果仅在参数传递模式或调用约定或返回类型方面不同,则在编译时返回重写错误,
    • 否则只允许对任何其他签名差异进行镜像,对应于两种方法都可以超载的情况。
作为虚拟方法的属性不会由导出类型中的重写方法隐式继承。

调用虚拟方法时,编译器可能需要执行一个vtable查找才能找出给定对象必须调用哪个方法。这需要使用虚拟方法在每个类型的顶部添加一个额外的隐藏的vtable指针字段。这个隐藏的vptr由内置的Object类型提供。因此,虚拟方法只能以直接或间接的方式声明ExtendsObject.

构造函数由于创建对象而无法进行虚拟化,而虚拟方法需要具有特定类型的已存在对象。要在编译时从代码中确定要调用的构造函数的类型。
此外,当在构造函数中调用虚拟方法时,仅使用本地版本的方法。这是因为vptr尚未由派生类型构造函数设置,而仅由本地类型构造函数设置。

析构函数通常在删除通过指向其基本类型的指针进行操作的对象时必须是虚拟的,以便破坏从最为导出的类型开始,并以其基本类型的方式工作。为了做到这一点,可能需要在没有必要的显式破坏的地方添加一个空体的虚拟析构函数,以便替代由其基础中的析构函数引起的每个非虚拟隐式析构函数。
另一方面,当在析构函数(虚拟或非虚拟)中调用虚拟(或抽象)方法时,仅使用该方法的本地版本,因为vptr根据其自身类型的vtable在析构函数的顶部重置。这避免访问子方法,因此引用先前被子析构函数执行破坏的子成员。

对于其声明中的Virtual的成员方法,也可以在相应的方法体上指定Virtual,以提高代码可读性。

注意:在多级继承中,在每个继承层次结构级别,可以声明相同的命名方法(相同的标识符和签名)AbstractVirtual或普通(不带说明符)。当混合说明符时,通常的顺序是从继承层次结构的上到下是抽象的 - >.
内部多态性进程不考虑重写方法的访问控制(Public/ Protected/ Private),而仅在编译时对初始调用进行考虑。
Base.method()始终调用自己的方法,而不是重写方法。
派生静态方法不能覆盖基本的虚拟/抽象方法,但可以影响任何基本方法(包括虚拟/抽象)。

例子

Type Hello extends object
    Declare virtual Sub hi( )
End Type

Type HelloEnglish extends Hello
    Declare Sub hi( )
End Type

Type HelloFrench extends Hello
    Declare Sub hi( )
End Type

Type HelloGerman extends Hello
    Declare Sub hi( )
End Type


Sub Hello.hi( )
    Print "hi!"
End Sub

Sub HelloEnglish.hi( )
    Print "你好!"
End Sub

Sub HelloFrench.hi( )
    Print "干杯!ca"
End Sub

Sub HelloGerman.hi( )
    Print "您好!"
End Sub


    Randomize( Timer( ) )

    Dim As Hello Ptr h

    For i As Integer = 0 To 9
        Select Case( Int( Rnd( ) * 4 ) + 1 )
        Case 1
            h = New HelloEnglish
        Case 2
            h = New HelloFrench
        Case 3
            h = New HelloGerman
        Case Else
            h = New Hello
        End Select

        h->hi( )
        Delete h
    Next

方言差异

与QB差别

  • 新的FreeBASIC

参考