如何在 Fortran 中重写结构体构造函数

2023-12-29

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

编辑:我遇到过一个错误报告 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39427 and an 宣布补丁 http://gcc.gnu.org/ml/fortran/2010-10/msg00274.html向 gfortran 询问此问题。但是,我尝试使用 11 月版本的 gcc46,但没有成功并出现类似错误。

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


目前是否可以重写 Fortran 中的结构构造函数?

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

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

考虑到这一事实,我完全不明白两者之间的真正区别是什么

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

and

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

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

好吧,老实说,这是有区别的,而且是巨大的区别——第一种方法是误导性的。这个函数不是构造函数(因为 Fortran 中根本没有 OOP 构造函数),它是一个初始值设定项。


在主流的 OOP 构造函数中,构造函数负责顺序执行两件事:

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

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

In Java:

MyType mt = new MyType(1);

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

MyType* mt = new MyType(1);

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

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

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

MyType mt(1);

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

In Python

mt = MyType(1)

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


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

我在某处读到,Fortran 中的模块概念受到 Modula-2 的启发。在我看来,OOP 功能的灵感来自于Oberon-2 http://en.wikipedia.org/wiki/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) for this arg of init子程序似乎没问题。因为我们希望该方法仅在分配后调用一次。控制这个假设不会是错误的可能是个好主意。添加一些布尔标志LOGICAL :: inited to mytype,检查是否是.false.并将其设置为.true.首次初始化时,并在尝试重新初始化时执行其他操作。我肯定记得 Google 网上论坛中有一些关于它的帖子...我找不到它。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Fortran 中重写结构体构造函数 的相关文章

随机推荐

  • 使用 Rest API 从 LogAnalytics Workspace 获取日志数据

    I am trying to fetch log data from Azure Log Analytics workspace with the queries that I have saved inside the workspace
  • 使用 EntityFramework Extended 批量插入

    根据this https code msdn microsoft com entity framework batch 994cd739 可以使用以下代码在实体中批量插入 var customers GetCustomers db Cust
  • FacebookShare 更新后导致编译器错误

    我刚刚跑了pod update对于我的应用程序 现在它无法编译 给出这些问题LinkShareContent swift in FacebookShare Cannot assign to property contentDescripti
  • C++ 运行时通过字符串名称访问成员函数

    我有两节课 class MyClassInfo public void AddMethod std string name void pointer I don t know what signature should be class M
  • 重命名 auth_user 会破坏新设置的迁移

    遵循看起来像好建议 https stackoverflow com questions 14904046 migrating existing auth user data to new django 1 5 custom user mod
  • 获取 Active Storage 变体的元数据

    我有一个 Active Storage 图像变体 例如 我正在尝试获取width and height该变体的值 因为它们是未知的 用于width and heightHTML 属性 我预计他们会在这里 model logo image v
  • 使用 xslt:analyze-string 将首字母缩略词添加到 HTML

    我想使用 xslt analyze string 将首字母缩略词添加到 HTML 文本中 问题 在我的 HTML 文本中有诸如 strong some text strong 被视为 XML 节点 当我应用 xslt analyze str
  • 我无法启用推送通知参数

    我三个月前创建了一个应用程序 并已成功批准进入 itunes 我需要做出的改进之一是包括 推送通知 问题是 当我尝试在developer apple com 的 App ID 中编辑该参数时 复选框被禁用 我无法检查它 这是他们告诉我们应该
  • 底部应用栏在使用片段导航时向上/向下滑动(导航架构组件)

    我正在查看底部应用程序栏 有一个很好的功能可以在滚动时隐藏它app hideOnScroll true 问题是我无法弄清楚当片段被删除时如何以编程方式向上或向下滑动它导航至和来自 例如 设置概述 开MainActivity具有导航主机片段
  • Fortran 中任何类型数组的过程

    Basis 我想编写一个过程 对任何输入数组类型进行一些操作 integer real 4 real 8 我在 StackOverflow 上读到的唯一想法是模仿 C 模板 使用通用过程进行覆盖 使用预处理器包含重复代码 但是搜索流行的I
  • 内存泄漏、访问已释放的内存和双重释放之间有什么区别?

    我试图找出与内存模型相关的这三种问题之间的区别 如果我想模拟一个memory leak场景中 我可以创建一个指针而不调用相应的删除方法 int main OK int p new int delete p Memory leak int q
  • 如何更改 conemu 中的字符集/区域设置?

    我通过 conemu 使用 gitbash 我有一个字符集问题 其中字符在 git bash 中通过 conemu 和直接 git bash 看起来错误 我通过将 minttyrc 中的区域设置设置为 在 gitbash 中修复了它 Bol
  • 何时使用嵌入式数据库

    我正在编写一个应用程序 它解析一个大文件 生成大量数据并用它进行一些复杂的可视化 由于所有这些数据无法保存在内存中 因此我做了一些研究 并开始考虑将嵌入式数据库作为这些数据的临时容器 我的问题是 这是解决这个问题的传统方法吗 嵌入式数据库
  • 命名约定:寻找混合英语和领域/工作流术语的替代方案

    尽管在我们公司 所有人的母语都不是英语 但我们还是努力用英语编写文档 代码和注释 当然 除了与用户相关的内容之外 几乎所有内容都是如此 只要业务术语是可翻译的并且不太特定于该领域 这就可以了 但是 一旦业务术语变得过于具体 要么没有适当的翻
  • Apache 重写子网 IP 范围

    有人可以告诉我如何将以下 IP 范围 属于 Cloudfront 放入 mod rewrite 中吗 我希望将 example com 的非 www 请求重定向到 www example com 但不重定向来自以下 IP 范围的任何 IP
  • 为什么我必须刷新页面才能使 JavaScript 函数正常工作?

    我正在开发一个移动网站并使用 jQuery 当我加载某个页面并单击所需的按钮时 代码在刷新页面之前不会执行 为什么是这样 我是这样的 script js document ready function user save click fun
  • CAShapeLayer 的中风结束没有动画

    这是我用来制作动画的代码CAShapeLayer progressBarLayer strokeEnd CGFloat progressToDrawForProgress progress let progressAnimation CAB
  • 将 git 存储库复制到 USB 驱动器

    我正在开发一个开源项目 我的机器上有一个包含所有代码的 git 存储库 该存储库有点大 我想在无法访问我的计算机时继续处理它 如果我将存储库复制到我的 USB 驱动器中 它的行为是否仍然像我在计算机中的原始存储库上一样 相同的配置等 如果复
  • 如何在 where 子句中使用 row_number

    我正在尝试使用窗口函数来获取最近的 n 条记录 如下从这里 https stackoverflow com questions 61570170 something like select distinct on but for n 1 6
  • 如何在 Fortran 中重写结构体构造函数

    目前是否可以重写 Fortran 中的结构构造函数 我见过这样的建议示例 例如在 Fortran 2003 规范中 module mymod type mytype integer x Other stuff end type interf