gpt4 book ai didi

constructor - 如何覆盖fortran中的结构构造函数

转载 作者:行者123 更新时间:2023-12-03 21:24:36 27 4
gpt4 key购买 nike

目前是否可以覆盖 Fortran 中的结构构造函数?我见过这样的提议示例(例如在 Fortran 2003 规范中):

module mymod

type mytype
integer :: x
! Other stuff
end type

interface mytype
module procedure init_mytype
end interface

contains
type(mytype) function init_mytype(i)
integer, intent(in) :: i
if(i > 0) then
init_mytype%x = 1
else
init_mytype%x = 2
end if
end function
end

program test
use mymod
type(mytype) :: x
x = mytype(0)
end program

由于冗余变量名称,这基本上会产生一堆错误(例如,错误:'mytype' 的 DERIVED 属性与 (1) 处的 PROCEDURE 属性冲突)。 Fortran 2003 示例的逐字副本会生成类似的错误。我已经在 gfortran 4.4、ifort 10.1 和 11.1 中尝试过这个,它们都产生了相同的错误。

我的问题:这只是 fortran 2003 的一个未实现的功能吗?还是我错误地实现了这个?

编辑:我遇到了一个 bug report和一个 announced patch gfortran 关于这个问题。但是,我尝试使用 11 月构建的 gcc46,但没有运气和类似的错误。

编辑 2:上面的代码似乎可以使用 Intel Fortran 12.1.0。

最佳答案

Is it currently possible to override the structure constructor in Fortran?



无论如何,即使使用您的方法也完全不是关于构造函数覆盖。主要原因是结构构造函数#OOP构造函数。有一些相似之处,但这只是另一个想法。

您不能在初始化表达式中使用您的非内在函数。您只能使用常量、数组或结构构造函数、内部函数……有关更多信息,请查看 Fortran 2003 草案中的 7.1.7 初始化表达式。

考虑到这一事实,我完全不明白两者之间的真正区别是什么
type(mytype) :: x
x = mytype(0)


type(mytype) :: x
x = init_mytype(0)

以及在 mymod MODULE 中使用 INTERFACE 块的全部意义是什么。

好吧,老实说是有区别的,最大的区别 - 第一种方式具有误导性。这个函数不是构造函数(因为 Fortran 中根本没有 OOP 构造函数),它是一个初始化器。

在主流的 OOP 构造函数中,负责依次做两件事:
  • 内存分配。
  • 成员初始化。

  • 我们来看一些不同语言实例化类的例子。

    Java :
    MyType mt = new MyType(1);

    隐藏了一个非常重要的事实——对象实际上是一个指向类类型变量的指针。等效于 C++ 堆分配使用:
    MyType* mt = new MyType(1);

    但是在两种语言中都可以看到,即使在语法级别也反射(reflect)了两种构造函数的职责。它由两部分组成:关键字 new(分配)和构造函数名称(初始化)。在 Objective-C 语法这一事实更加强调:
    MyType* mt = [[MyType alloc] init:1];

    然而,很多时候,您可以看到一些其他形式的构造函数调用。在 的情况下堆栈上的分配 C++ 使用特殊(非常差)的语法结构
    MyType mt(1);

    这实际上具有误导性,以至于我们不能考虑它。

    python
    mt = MyType(1)

    对象实际上是一个指针的事实和首先发生分配的事实都是隐藏的(在语法级别)。而这个方法被称为... __init__ ! O_O 太误导了。 С++ 堆栈分配与那个相比逐渐消失。 =)

    无论如何,拥有 的想法构造函数在语言中暗示做事的能力 在一个语句中分配一个初始化 使用某种特殊的方法。如果您认为这是“真正的 OOP”方式,我有一个坏消息要告诉您。偶 Smalltalk doesn't have constructors .拥有 new 只是惯例类本身的方法(它们是元类的单例对象)。 Factory Design Pattern用于许多其他语言以实现相同的目标。

    我在某处读到 Fortran 中的模块概念受到 Modula-2 的启发。在我看来,OOP 功能的灵感来自 Oberon-2 . Oberon-2 中也没有构造函数。但是当然有预先声明的过程 NEW 的纯分配(如 Fortran 中的 ALLOCATE,但 ALLOCATE 是语句)。分配后你可以(在实践中应该)调用一些初始化器,这只是一个普通的方法。那里没什么特别的。

    所以你可以使用某种工厂来初始化对象。这就是您使用模块而不是单例对象实际执行的操作。或者最好说他们(Java/C#/...程序员)使用单例对象方法而不是普通函数,因为缺少后者(没有模块 - 没有办法拥有普通函数,只有方法)。

    您也可以改用类型绑定(bind)的 SUBROUTINE。
    MODULE mymod

    TYPE mytype
    PRIVATE
    INTEGER :: x
    CONTAINS
    PROCEDURE, PASS :: init
    END TYPE

    CONTAINS

    SUBROUTINE init(this, i)
    CLASS(mytype), INTENT(OUT) :: this
    INTEGER, INTENT(IN) :: i

    IF(i > 0) THEN
    this%x = 1
    ELSE
    this%x = 2
    END IF
    END SUBROUTINE init

    END

    PROGRAM test

    USE mymod

    TYPE(mytype) :: x

    CALL x%init(1)

    END PROGRAM
    INTENT(OUT)this init 的参数SUBROUTINE 似乎没问题。因为我们希望这个方法在分配后只被调用一次。控制这个假设不会出错可能是个好主意。添加一些 bool 标志 LOGICAL :: initedmytype , 检查是否是 .false.并将其设置为 .true.在第一次初始化时,并在尝试重新初始化时做其他事情。我绝对记得 Google Groups 中关于它的一些线程......我找不到它。

    关于constructor - 如何覆盖fortran中的结构构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4262253/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com