在 Fortran 中访问子声明类型的问题

Problem with accessing child declared type in Fortran

考虑以下代码

  module class_type

  implicit none
  class(*), pointer :: fnzo => null()


  type, abstract :: gen

     real :: ss
     integer :: sdsd
     class(gen), pointer    :: next =>null()
  end type

  type, extends(gen) :: final1

     real :: ss1

  end type final1

  type, extends(gen) :: final2

  real :: x1(10)

  end type


  end module class_type



  program test_class

  use class_type

  implicit none

  class(gen), pointer :: test
  type(final1) :: test1
  allocate(test, source = test1)

  print*, test% ss1




  end program

我正在尝试创建一个链表,其中每个下一个元素继承 final1final2。目前,只是测试简单的案例,我不明白为什么我无法访问test%ss1。有人帮忙

为了访问 ss1,您的抽象 class 中需要一个指向子对象的指针。指针可以是您希望定义的任一类型扩展。由于您的链表有两个不同的类型扩展,因此您需要在摘要 class.

中声明两个子指针
module class_type

  implicit none
  class(*), pointer :: fnzo => null()


  type, abstract :: gen

     real :: ss
     integer :: sdsd
     class(gen), pointer    :: next =>null()
     type(final1), pointer  :: child
  end type

  type, extends(gen) :: final1

     real :: ss1

  end type final1

  type, extends(gen) :: final2

     real :: x1(10)

  end type final2


end module class_type



program test_class

  use class_type

  implicit none

  class(gen), pointer  :: test
  type(final1), target    :: test1

  allocate(test, source=test1)

  test1% ss1 = 20.0
  test% child => test1

  write(*,*) test1% ss1

  write(*,*) test% child% ss1

end program test_class

当你编译并执行时,你会看到:

   20.00000    
   20.00000

至于"why we cannot access test% ss1",下面的代码可能有助于思考原因。在此代码中,我获得用户输入 (inp) 并确定 ptr 是否指向 test1test2 类型的变量。如果ptr指向test2的一个变量,那么访问ptr% ss1显然是没有意义的,所以编译器需要防范这种不正确的访问。我认为这就是为什么编译器只允许访问 gen(=声明类型)的组件,除非提供 select type(对于内存中的实际数据)。

program test_class
  use class_type
  implicit none
  class(gen), pointer  :: ptr    !! parent type
  type(final1), target :: test1  !! child type
  type(final2), target :: test2  !! child type
  integer :: inp

  print *, "input some integer"
  read *, inp

  if ( inp == 1 ) ptr => test1
  if ( inp == 2 ) ptr => test2

  print*, "ptr% ss = ", ptr% ss   !! OK

  ! print*, "ptr% ss1 = ", ptr% ss1  !! error (Line1)

  select type ( ptr )
    type is ( final1 ); print*, "ss1 = ", ptr% ss1  !! OK
    type is ( final2 ); print*, "x1  = ", ptr% x1   !! OK
  endselect

end program

如果 Line1 没有注释,它会报错(使用 gfortran-8)

   print*, "ptr% ss1 = ", ptr% ss1  !! error
                             1
Error: 'ss1' at (1) is not a member of the 'gen' structure; did you mean 'ss'?

我想情况与其他(静态类型)语言类似。例如下面的C++代码在我们访问ptr->b.

时报错
#include <iostream>
using namespace std;

struct A {
    int a = 1;
};
struct B : A {
    int b = 100;
};

int main() {
    A *ptr;
    ptr = new B;
    cout << ptr->a << endl;     // 1
    // cout << ptr->b << endl;  // error: 'struct A' has no member named 'b'
    delete ptr;
}