मैं पॉलिमॉर्फिक ऑब्जेक्ट्स की एक सरणी बनाना चाहता हूं जिसमें रचनाकार उनके गतिशील प्रकार के आधार पर अलग-अलग डमी तर्क ले रहे हों। उपयोगकर्ता द्वारा परिभाषित और संरचना निर्माणकर्ताओं के बारे में पढ़ने के बाद, मुझे इन अवधारणाओं को गतिशील रूप से आवंटित वस्तुओं पर लागू करने का कोई तरीका नहीं दिखता है। सी ++ में पृष्ठभूमि होने के कारण, मुझे इस धारणा के लिए उपयोग किया जाता था कि वस्तुओं को गतिशील रूप से या ढेर पर आवंटित करते समय मैं एक और एक ही कन्स्ट्रक्टर "सदस्य फ़ंक्शन" का उपयोग कर सकता हूं, लेकिन मैं आवंटित वस्तुओं पर उपयोगकर्ता द्वारा परिभाषित फोरट्रान कन्स्ट्रक्टर को स्पष्ट रूप से कैसे कॉल कर सकता हूं?

इसके बजाय, मैंने जेनेरिक और टाइप-बाउंड इनिट फ़ंक्शंस के साथ फील करने की कोशिश की:

module mod
type :: basis_t
contains
    procedure, public :: init_func => init_base
    ! I want a generic constructor function
    generic, public   :: init => init_func 
end type

type, extends(basis_t) :: extended_t
contains
    ! cannot work, init_extended has a different signature from init_base
    procedure, public :: init => init_extended 
end type

type wrapper_t
   type(basis_t), pointer :: obj
end type

contains
   subroutine init_base(this)
      class(base_t), intent(inout) :: this
   end subroutine

   subroutine init_extended(this, param)
      class(extended_t), intent(inout) :: this
      integer :: param
   end subroutine
end module

program
   use mod
   implicit none

   type(wrapper_t) :: arr(2)
   allocate(basis_t::arr(1)%obj)
   allocate(extended_t::arr(2)%obj)
   call arr(1)%obj%init    ! calls init_basis
   call arr(2)%obj%init(4) ! calls init_extended
end program

लेकिन मुझे विश्वास नहीं है कि मैं सही रास्ते पर हूँ, जैसे कि उदा। सी ++ मैं इसके बजाय उदा।

basis_t* arr[2];
arr[0] = new basis_t;
arr[1] = new extended_t{ 4 };

महत्वपूर्ण अंतर यह है कि C++ में कंस्ट्रक्टर्स नहीं टाइप-बाउंड/वर्चुअल हैं, जैसा कि मेरे फोरट्रान दृष्टिकोण में है। मैं क्या कर सकता हूँ?

2
Jodocus 7 नवम्बर 2019, 16:16

1 उत्तर

सबसे बढ़िया उत्तर

फोरट्रान में एक कंस्ट्रक्टर की भूमिका निम्न द्वारा प्रदान की जा सकती है:

  • भाषा ने स्ट्रक्चर कंस्ट्रक्टर प्रदान किया।

  • एक परिणाम के साथ एक फ़ंक्शन जो ऑब्जेक्ट के प्रकार का निर्माण किया जा रहा है। भाषा एक सामान्य फ़ंक्शन को व्युत्पन्न प्रकार के समान नाम रखने की अनुमति देती है, और आगे ऐसे फ़ंक्शन के संदर्भ को ओवरलोड करने की अनुमति देती है जो अन्यथा प्रकार के लिए संरचना निर्माता का संदर्भ होगा।

  • एक सबरूटीन जो उपयुक्त प्रकार के एक आशय (बाहर) तर्क को परिभाषित करता है।

आप जो उपयोग करते हैं वह कुछ हद तक परिस्थितियों और व्यक्तिगत पसंद पर निर्भर करता है। भाषा प्रदान की गई संरचना निर्माता कुछ परिस्थितियों में निरंतर अभिव्यक्तियों में उपयोग किया जा सकता है, लेकिन केवल घटकों की सरल मूल्य परिभाषा की अनुमति देता है (कोई निष्पादन योग्य कोड नहीं); फ़ंक्शन संदर्भ प्रपत्र आपको ऑब्जेक्ट निर्माण के हिस्से के रूप में मनमाने कोड को निष्पादित करने की अनुमति देता है, निरंतर अभिव्यक्तियों में उपयोग नहीं किया जा सकता है, आसानी से निर्माण विफलता का संकेत नहीं दे सकता है और महंगा हो सकता है (फोरट्रान प्रोसेसर कार्यान्वयन विवरण के आधार पर) यदि निर्मित वस्तु बड़ी है; सबरूटीन फॉर्म के लिए एक अलग कॉल स्टेटमेंट की आवश्यकता होती है (कन्स्ट्रक्टर एक बड़ी अभिव्यक्ति का हिस्सा नहीं हो सकता है) और सामान्य नाम/संरचना अधिभार भाषा सुविधा का लाभ नहीं उठा सकता है।

उन तीन विधियों में से कोई भी एक प्रकार की बाध्य प्रक्रिया शामिल नहीं है। ऐसी कुछ परिस्थितियां हैं जहां एक प्रकार की बाध्य प्रक्रिया ऑब्जेक्ट परिभाषा के लिए उपयुक्त हो सकती है (एक प्रकार की बाध्य प्रक्रिया जिसका उद्देश्य किसी फ़ाइल से ऑब्जेक्ट मान को पढ़ना है, उदाहरण के लिए - एक्सटेंशन पदानुक्रम में सभी प्रकारों को फ़ाइल के बारे में समान जानकारी की आवश्यकता होती है जिसे पास किया जाना है। उन्हें), लेकिन यह निर्माण के लिए सामान्य अर्थ नहीं रखता है, जहां आप वस्तु के प्रकार को परिभाषित कर रहे हैं और साथ ही इसके मूल्य को परिभाषित कर रहे हैं।

फोरट्रान में पॉइंटर्स ज्यादातर संदर्भ शब्दार्थ के लिए उपयोग किए जाते हैं (क्योंकि वे संदर्भ हैं)। यदि आप मूल्य शब्दार्थ चाहते हैं तो आप आम तौर पर उनका उपयोग नहीं करना चाहते हैं - आवंटन का उपयोग करें।

TYPE :: ta
  INTEGER :: a
END TYPE ta

TYPE, EXTENDS(ta) :: tb
  REAL :: b
END TYPE :: tb

INTERFACE tb
  PROCEDURE :: tb_construct
END INTERFACE tb

TYPE, EXTENDS(ta) :: tc
END TYPE tc

TYPE :: ta_item
  CLASS(ta), ALLOCATABLE :: item
END TYPE ta_item

!...

FUNCTION tb_construct(arg)
  INTEGER, INTENT(IN) :: arg
  TYPE(tb) :: tb_construct
  tb_construct%a = arg + 1
  tb_construct%b = arg / 2.0
END FUNCTION tb_construct

SUBROUTINE ConstructTC(obj, arg, stat)
  CLASS(ta), INTENT(OUT), ALLOCATABLE :: obj
  INTEGER, INTENT(IN) :: arg
  INTEGER, INTENT(OUT) :: stat
  TYPE(tc), ALLOCATABLE :: tmp
  IF (arg < 0) THEN
    ! Construction failed.
    stat = 1
    RETURN
  END IF
  tmp%a = arg + 4
  CALL MOVE_ALLOC(tmp, obj)
  stat = 0    ! Construction succeeded.
END SUBROUTINE ConstructTC

!...

TYPE(ta_item) :: the_items(3)
INTEGER :: stat

! Structure constructor
the_items(1)%item = ta(1)

! Overloaded function.
the_items(2)%item = tb(2)

! Subroutine.
CALL ConstructTC(the_items(3)%item, 3, stat)
IF (stat /= 0) ERROR STOP 'It failed.'
3
IanH 8 नवम्बर 2019, 07:21