【问题标题】:How to use polymorphic data type as attribute of another data type in Fortran如何在 Fortran 中使用多态数据类型作为另一种数据类型的属性
【发布时间】:2019-12-12 11:18:04
【问题描述】:

我创建了一个名为“元素”的类,它有几个属性和类型绑定的过程。其中一个属性是具有两个继承类型“kin1”和“kin2”的抽象类类型“kin”。我希望能够在运行时根据输入使用构造函数将“kin1”或“kin2”作为属性分配给对象“元素”。目标是有一个元素列表,每个元素的 element%kin 要么是“kin1”类型,要么是“kin2”类型。

模块元素

模块元素

使用亲属

implicit none

type,public :: element_type
    class(kin_type),allocatable :: kin
contains
    procedure,pass(this), private :: set_kin
    procedure,pass(this), public  :: get_kin
end type element_type

interface element_type
    module procedure element_type_constructor
end interface element_type 

包含

type (element_type) function element_type_constructor(kin)
    implicit none             
    class(kin_type),allocatable,  intent (in) :: kin    
    call element_type_constructor%set_kin(kin)
end function element_type_constructor

! my try of set_kin
subroutine set_kin(this,kin)
implicit none
class(element_type), intent(inout) :: this
class(kin_type),allocatable, intent(in) :: kin
this%kin = kin
end subroutine

结束模块元素

模块亲属

模块亲属 隐式无 私人的

type,abstract :: kin_type
end type kin_type

type,public, extends(kin_type) :: kin1_type
    private
    integer :: data1
contains
    procedure,pass(this),private :: set_data1
    procedure,pass(this),public  :: get_data1
    procedure,pass(this),public  :: print =>print_kin1
end type kin1_type

type,public, extends(kin1_type) :: kin2_type
    private
    real :: data2
contains
    procedure,pass(this),private :: set_data2
    procedure,pass(this),public  :: get_data2
    procedure,pass(this),public  :: print =>print_kin2
end type kin2_type

! constructor interface kin1_type
interface kin1_type
    module procedure kin1_type_constructor
end interface kin1_type

! constructor interface kin2_type
interface kin2_type
    module procedure kin2_type_constructor
end interface kin2_type

包含

! constructor kin1_type
type (kin1_type) function kin1_type_constructor(data1)
    implicit none
    integer,          intent (in) :: data1                
    class(kin1_type), intent (in) :: kin    
    call kin1_type_constructor%set_data1(data1)
end function kin1_type_constructor

! constructor kin2_type
type (kin2_type) function kin1_type_constructor(data1,data2)
    implicit none
    integer,          intent (in) :: data1 
    real,             intent (in) :: data2               
    class(kin2_type), intent (in) :: kin    
    call kin2_type_constructor%set_data1(data1)
    call kin2_type_constructor%set_data2(data2)
end function kin2_type_constructor


! Example of set subroutine
subroutine set_data1(this,data1)
    class(kin1_type),intent(inout) :: this    
    integer,         intent(in)    :: data1
    this%data1 = data1
end subroutine set_data1 

!其他程序...

结束模块kin

程序

程序测试

use element
use kin

implicit none
type(element_type) :: thisElement
type(kin1_type)    :: thisKin1

! constructor for thisKin1
thisKin1 = kin1_constructor(data1 = 1)

! constructor for thisElement
thisElement = element_type_constructor(kin = thisKin1)

! Check kin structure and values
call thisElement%kin%print

结束程序

错误

我在 element_type_constructor 子例程运行期间收到以下错误: 程序收到信号 SIGSEGV:分段错误 - 内存引用无效。

【问题讨论】:

    标签: oop fortran2008


    【解决方案1】:

    我还不能发表评论,所以这是第一个答案:不幸的是,提供的代码不完整。此外,缺少编译器的供应商和版本,这使得很难猜测实际问题是什么。

    “修复”代码以获取以下示例表明它在原则上工作:

    kin.f90:

    module kin
        implicit none
        private
    
        type,abstract,public :: kin_type
        contains
            procedure(print_iface), deferred :: print
        end type kin_type
    
        type,public, extends(kin_type) :: kin1_type
            private
            integer :: data1
        contains
            procedure,pass(this),private :: set_data1
            procedure,pass(this),public :: print => print_kin1
        end type kin1_type
    
        ! constructor interface kin1_type
        interface kin1_type
            module procedure kin1_type_constructor
        end interface kin1_type
    
        abstract interface
            subroutine print_iface(this)
                import kin_type
                class(kin_type), intent(in) :: this
            end subroutine
        end interface
    contains
    
        ! constructor kin1_type
        type (kin1_type) function kin1_type_constructor(data1)
            implicit none
            integer,          intent (in) :: data1
            call kin1_type_constructor%set_data1(data1)
        end function kin1_type_constructor
    
        ! Example of set subroutine
        subroutine set_data1(this,data1)
        class(kin1_type),intent(inout) :: this
            integer,         intent(in)    :: data1
            this%data1 = data1
        end subroutine set_data1
    
        subroutine print_kin1(this)
            class(kin1_type),intent(in) :: this
            print *, this%data1
        end subroutine print_kin1
    
    end module kin
    

    element.f90:

    module element
        use kin, only: kin_type
    
        implicit none
    
        type,public :: element_type
            class(kin_type), allocatable :: kin
        contains
            procedure,pass(this), private :: set_kin
        end type element_type
    
        interface element_type
            module procedure element_type_constructor
        end interface element_type
    contains
    
        type (element_type) function element_type_constructor(kin)
            implicit none
            class(kin_type), intent (in) :: kin
            call element_type_constructor%set_kin(kin)
        end function element_type_constructor
    
        ! my try of set_kin
        subroutine set_kin(this,kin)
            implicit none
            class(element_type), intent(inout) :: this
            class(kin_type), intent(in) :: kin
            this%kin = kin
        end subroutine
    end module element
    

    ma​​in.f90:

    program test
    
        use element
        use kin
    
        implicit none
        type(element_type) :: thisElement
        class(kin_type), allocatable :: thisKin1
    
        ! constructor for thisKin1
        thisKin1 = kin1_type(data1 = 1)
    
        ! constructor for thisElement
        thisElement = element_type(kin = thisKin1)
    
        call thisElement%kin%print()
    end program
    

    使用 gfortran 7.4.0 构建它并运行它会产生:

    $ gfortran -o prog kin.f90 element.f90 main.f90
    $ ./prog 
               1
    $
    

    与所提供的内容的一个显着区别是抽象类型上的延迟print 过程,因为它是通过定义为class(kin_type) 的属性调用的。不幸的是,这并不能解释引用的错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-12
      • 2010-11-22
      • 1970-01-01
      • 2012-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多