Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Inheritance 理解Fortran扩展了类型和覆盖_Inheritance_Polymorphism_Fortran_Overriding - Fatal编程技术网

Inheritance 理解Fortran扩展了类型和覆盖

Inheritance 理解Fortran扩展了类型和覆盖,inheritance,polymorphism,fortran,overriding,Inheritance,Polymorphism,Fortran,Overriding,我试图理解Fortran 2003标准(或更高版本)中的面向对象概念。我在C++中有一些知识,所以我认为这两种语言之间有一些共同的想法,这可以帮助我更好地理解它们。p> 在C++中,多态性是通过类派生和成员函数重写来完成的。其中一个定义了一个“抽象”基类,其中定义了几乎所有的虚函数。不同的派生类包含它们的实际实现。所以其他函数只需要基于“抽象”类进行编程。然后,它们适用于所有派生类 我认为在Fortran中,OOP是以类似的方式完成的,但有一些不同之处。在我看来,需要定义一个具有C++的一些虚拟

我试图理解Fortran 2003标准(或更高版本)中的面向对象概念。我在C++中有一些知识,所以我认为这两种语言之间有一些共同的想法,这可以帮助我更好地理解它们。p> 在C++中,多态性是通过类派生和成员函数重写来完成的。其中一个定义了一个“抽象”基类,其中定义了几乎所有的虚函数。不同的派生类包含它们的实际实现。所以其他函数只需要基于“抽象”类进行编程。然后,它们适用于所有派生类

我认为在Fortran中,OOP是以类似的方式完成的,但有一些不同之处。在我看来,需要定义一个具有C++的一些虚拟函数的基类型。其他函数/子例程应遵循基类型中的成员函数定义。这是解决所有扩展类型的函数/子例程重用问题的方法

我没有更好的办法来规划这个想法。这是我的第一次尝试:

type Basis
    integer                                 :: NBasis
contains
    private
    procedure                               :: DoNothing
    generic, public                         :: Constructor => DoNothing
    generic, public                         :: AllocateBasis => DoNothing
endtype Basis

type, extends(Basis) :: GridBasis
    private
    integer                                 :: NGrid
contains
    private
    procedure                               :: ConstructorGrid1
    procedure                               :: ConstructorGrid2
    generic, public                         :: Constructor => ConstructorGrid1, ConstructorGrid2, ConstructorGrid3
    procedure                               :: AllocateGridReal
    procedure                               :: AllocateGridCplx
    generic, public                         :: AllocateBasis => AllocateGridReal, AllocateGridCplx
endtype GridBasis
  • 首先,我如何在类型基础中定义“AllocateBasis”,使其像“虚拟函数”一样工作,并且所有扩展类型都必须定义自己版本的“AllocateBasis”

  • 第二,如何在GridBasis类型中定义“AllocateBasis”?这里的定义包含了它的实际实现

  • 第三,如何使GridBasis类型中的“AllocateBasis”成为重载函数?i、 e.有实版本和复版本,它们都被命名为“AllocateBasis”,具有实或复输入可分配数组

  • 第四,不传球对传球。据我所知,如果设置了PASS,则有一个指向该对象的显式指针。但是,当没有通行证时,就没有这样的事情。那么,通行证是为了澄清而简化的吗


首先对您的问题给出一些评论/答案:

  • 您可以将类型绑定过程声明为“延迟”。然后您必须只定义它的签名(接口),而不需要特定的实现。必须声明包含
    延迟
    过程的类型
    摘要
    。此类类型无法实例化。所有扩展类型都必须为给定过程提供实现,除非它们本身是
    抽象的

  • 为了在扩展类型中为延迟的过程提供实现,只需在扩展类型中声明该过程并为其提供实现

  • 不能将给定类型的公共过程转换为扩展类型中的
    泛型
    。但是,您可以在基类型中定义一个
    泛型
    ,并在其派生类型中对其进行扩展

  • 默认情况下设置
    pass
    属性,因此过程的第一个参数将是类型实例。但是,您可以指定它以使其更明确。此外,您可以在
    PASS(ARGNAME)
    的形式中使用它来指定哪个参数(
    ARGNAME
    )应该是实例。此参数不必是过程中的第一个参数

下面是一个自我包含的示例,其中应包含您要求的所有功能:

module basis_module
  implicit none

  type, abstract :: Basis
    integer :: NBasis
  contains
    procedure(allocBasisR1Interface), deferred :: allocateBasisR1
    generic :: allocateBasis => allocateBasisR1
  end type Basis

  interface 
    ! Interface for real basis allocation
    subroutine allocBasisR1Interface(self, array)
      import
      class(Basis), intent(inout) :: self
      real, intent(in) :: array(:)
    end subroutine allocBasisR1Interface
  end interface

end module basis_module


module extension_module
  use basis_module
  implicit none

  type, extends(Basis) :: GridBasis
  contains
    ! Extending the mapping allocateBasis => allocateBasisR1 of
    ! the parent type.
    generic :: allocateBasis => allocateBasisC1
    procedure :: allocateBasisC1
    ! Implementation for the deferred procedure in Basis
    procedure :: allocateBasisR1
  end type GridBasis

contains

  subroutine allocateBasisR1(self, array)
    class(GridBasis), intent(inout) :: self
    real, intent(in) :: array(:)

    self%NBasis = size(array)
    print *, "GridBasis:allocateBasisR1"

  end subroutine allocateBasisR1


  subroutine allocateBasisC1(self, array)
    class(GridBasis), intent(inout) :: self
    complex, intent(in) :: array(:)

    self%NBasis = size(array)
    print *, "GridBasis:allocateBasisC1"

  end subroutine allocateBasisC1

end module extension_module


program test
  use extension_module
  implicit none

  type(GridBasis) :: mybasis
  real :: myRealArray(10)
  complex :: myComplexArray(5)

  call mybasis%allocateBasis(myRealArray)
  call mybasis%allocateBasis(myComplexArray)

end program test

我的目标是分离解算器例程和基本类型。你是对的。我会立即在我的帖子中添加一个例子。谢谢你的回答:)你现在有了一个合理的一般答案,很容易适应你的具体情况。你的编辑澄清了你知道你不需要在任何地方都做基本的事情(但在这里很有用)!谢谢让我消化一会儿。好奇的是:你在不同的模块中分离基类型和扩展类型,或者仅仅是你的编程风格,这是我的编程风格,每种类型都使用不同的模块进行类型绑定。@Bálint Aradi,我知道这是一个过时的线程,但这段代码是否运行过?它在IVF 2012下生成了一个与符号“\u allocBasisR1Interface”相关的LNK2019错误,我缺乏必要的知识来修复它。@IronX是的。我刚刚试过gfortran 8.2。