Fortran中的继承与指针:链表派生类实现问询
Great question! Let's build a practical useful_link derived type from your basic link type step by step, adding data support and handy utility functions. Here's how to do it in Fortran:
link Type First, let's confirm the base type you described—one that only handles node creation and pointer linking:
type :: link type(link), pointer :: next => null() contains procedure :: create_node => link_create_node end type link subroutine link_create_node(this, new_node) class(link), intent(inout) :: this type(link), pointer, intent(out) :: new_node allocate(new_node) this%next => new_node end subroutine link_create_node
useful_link Type We'll extend link to add a data field (we'll use integer for this example, but you can swap it for real, character(*), or even another derived type) and implement utility methods for data handling, traversal, insertion, and deletion:
type, extends(link) :: useful_link integer :: data ! Customize this to your data type needs contains procedure :: create_node_with_data => useful_link_create_node_with_data procedure :: get_data => useful_link_get_data procedure :: set_data => useful_link_set_data procedure :: traverse => useful_link_traverse procedure :: insert_after => useful_link_insert_after procedure :: delete_next => useful_link_delete_next end type useful_link
Let's code each method to make the linked list functional:
3.1 Create a Node with Initial Data
This method creates a new node, sets its data, and links it to the current node's next pointer:
subroutine useful_link_create_node_with_data(this, new_node, data_val) class(useful_link), intent(inout) :: this type(useful_link), pointer, intent(out) :: new_node integer, intent(in) :: data_val allocate(new_node) new_node%data = data_val this%next => new_node ! Inherit the base type's linking logic end subroutine useful_link_create_node_with_data
3.2 Get/Set Node Data
Simple accessor methods to safely read and modify node data:
function useful_link_get_data(this) result(data_val) class(useful_link), intent(in) :: this integer :: data_val data_val = this%data end function useful_link_get_data subroutine useful_link_set_data(this, data_val) class(useful_link), intent(inout) :: this integer, intent(in) :: data_val this%data = data_val end subroutine useful_link_set_data
3.3 Traverse and Print the List
Debug and inspect your list by traversing all nodes and printing their data:
subroutine useful_link_traverse(this) class(useful_link), intent(in) :: this type(useful_link), pointer :: current current => this do while(associated(current)) print *, "Node data: ", current%get_data() ! Convert base type pointer to derived type (safe since we're using only useful_link nodes) select type(next_node => current%next) type is(useful_link) current => next_node class default exit ! Handle unexpected node types gracefully end select end do end subroutine useful_link_traverse
We use select type here for type safety—this ensures we only process valid useful_link nodes.
3.4 Insert a Node After the Current One
Add a new node with data immediately after the current node:
subroutine useful_link_insert_after(this, data_val) class(useful_link), intent(inout) :: this integer, intent(in) :: data_val type(useful_link), pointer :: temp_node, new_node allocate(new_node) new_node%data = data_val ! Save the current next node before overwriting it select type(temp_node => this%next) type is(useful_link) new_node%next => temp_node class default new_node%next => null() end select this%next => new_node end subroutine useful_link_insert_after
3.5 Delete the Next Node
Safely remove the node immediately after the current one, freeing its memory:
subroutine useful_link_delete_next(this) class(useful_link), intent(inout) :: this type(useful_link), pointer :: temp_node select type(temp_node => this%next) type is(useful_link) this%next => temp_node%next deallocate(temp_node) class default ! No valid useful_link node to delete—do nothing end select end subroutine useful_link_delete_next
Put it all together with a demo program:
program linked_list_demo type(useful_link), pointer :: head, current, new_node ! Initialize head node with data 0 allocate(head) head%set_data(0) ! Add nodes with data 10 and 20 call head%create_node_with_data(new_node, 10) current => new_node call current%create_node_with_data(new_node, 20) ! Insert a node with data 5 right after the head call head%insert_after(5) ! Traverse the list print *, "=== Initial List ===" call head%traverse() ! Delete the node with data 5 call head%delete_next() print *, new_line('a')//"=== After Deleting Node with Data 5 ===" call head%traverse() ! Clean up all nodes to avoid memory leaks current => head do while(associated(current)) type(useful_link), pointer :: temp temp => current current => null() select type(next_node => temp%next) type is(useful_link) current => next_node end select deallocate(temp) end do end program linked_list_demo
- Generic Data: To support multiple data types, use Fortran's generic type features (Fortran 2003+) or create separate derived types (e.g.,
useful_link_int,useful_link_real). - Error Handling: Add
statparameters toallocatecalls to catch memory allocation failures. - Type Safety: Always use
select typewhen casting base type pointers to derived types to avoid runtime errors.
内容的提问来源于stack exchange,提问作者bob.sacamento

