在 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
我正在尝试创建一个链表,其中每个下一个元素继承 final1
或 final2
。目前,只是测试简单的案例,我不明白为什么我无法访问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
是否指向 test1
或 test2
类型的变量。如果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;
}
考虑以下代码
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
我正在尝试创建一个链表,其中每个下一个元素继承 final1
或 final2
。目前,只是测试简单的案例,我不明白为什么我无法访问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
是否指向 test1
或 test2
类型的变量。如果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;
}