目前是否可以重写 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 未实现的功能吗?或者我错误地执行了此操作?

编辑:我遇到过一个 错误报告宣布补丁 向 gfortran 询问此问题。但是,我尝试使用 11 月版本的 gcc46,但没有成功并出现类似错误。

编辑2:上述代码似乎可以使用 Intel Fortran 12.1.0 运行。

有帮助吗?

解决方案

我咨询了Fortran的2008标准的副本。这确实允许您定义具有相同名称的派生类型的通用接口。虽然所以我留下怀疑(不包括2003标准手的复印件)我的编译器(英特尔Fortran 11.1)将不会编译代码,这是Fortran 2003标准的一个尚未 - 未实现的功能。

除此之外,还有就是在你的程序中的错误。你的函数声明:

  type(mytype) function init_mytype
    integer, intent(in) :: i

指定的存在和意图的参数,它是不存在的功能规范,这或许应该被重写为:

  type(mytype) function init_mytype(i)

其他提示

目前是否可以重写 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 构造函数中,构造函数负责顺序执行两件事:

  1. 内存分配。
  2. 成员初始化。

让我们看一下用不同语言实例化类的一些示例。

爪哇:

MyType mt = new MyType(1);

一个非常重要的事实被隐藏了——该对象实际上是一个指向类类型变量的指针。相当于 C++堆上的分配 使用:

MyType* mt = new MyType(1);

但在这两种语言中,我们可以看到即使在语法级别也反映了两种构造函数的职责。它由两部分组成:关键字 new(分配)和构造函数名称(初始化)。在 Objective-C 语法这个事实更加强调:

MyType* mt = [[MyType alloc] init:1];

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

MyType mt(1);

这实际上具有很大的误导性,我们可以不考虑它。

Python

mt = MyType(1)

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


无论如何,有一个想法 构造函数 在语言中暗示有能力做 在一条语句中分配初始化 使用某种特殊的方法。如果您认为这是“真正的 OOP”方式,那么我有坏消息要告诉您。甚至 短暂聊天 没有构造函数. 。这只是一个约定 new 类本身的方法(它们是元类的单例对象)。这 工厂设计模式 在许多其他语言中使用来实现相同的目标。

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

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

您也可以使用类型绑定的 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 子程序似乎没问题。因为我们希望该方法仅在分配后调用一次。控制这个假设不会是错误的可能是个好主意。添加一些布尔标志 LOGICAL :: initedmytype, ,检查是否是 .false. 并将其设置为 .true. 首次初始化时,并在尝试重新初始化时执行其他操作。我绝对记得 Google 网上论坛上有一些关于它的帖子......我找不到它。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top