غير قادر على الوصول إلى أعضاء معلمة ADA العامة

StackOverflow https://stackoverflow.com/questions/2338913

  •  22-09-2019
  •  | 
  •  

سؤال

أحاول كتابة حزمة عامة وأحد العمليات المطلوبة هو التحقق من سجلات البيانات المستلمة عبر ناقل. سيختلف نوع السجل وهو معلمة عامة. ومع ذلك ، فإن أي محاولات للوصول إلى أعضاء المعلمة العامة تسبب خطأ في التجميع.

الخطأ ... (ADA 95 GNAT 2009)

file.adb:XX no selector "Data" for private type "The_Transfer_Type" defined at file.ads:YY

الإعلان ...

generic
  type The_Transfer_Type is private;
  SIZE : Integer;
package CC_Test_Channel is
  function Checksum(Msg : The_Transfer_Type) return Integer;
end package

والجسم ...

function Checksum(Msg : The_Transfer_Type) return Integer is
  Sum : Integer := 0;
begin
  -- calculate the checksum
  for i in 1 .. SIZE loop
    Sum := Sum + Integer(Msg.Data(i));
  end loop;
  return Sum;
end Checksum;
هل كانت مفيدة؟

المحلول

عندما تحدد أن المعلمة العامة هي نوع خاص ، حسنًا ، تفترض ADA أنك تعني ذلك :-)

أي ليس لديك وصول إلى مكوناته. ADA ليس "بكت البط"، لذلك من غير المهم ما إذا كنت تعلم أن نوع إنشاء مثيله قد يمتلك بالفعل حقلًا معينًا. (كيف تتوقع أن تعمل وظيفة الاختبارات الخاصة بك إذا تم إنشاء معلمة the_transfer_type ، على سبيل المثال ، عدد صحيح؟)

تتمثل إحدى طرق معالجة ذلك أيضًا في توفير وظيفة ملحق كمعلمة إلى العام الذي سيسترجع البيانات اللازمة ، في هذه الحالة ، حساب الاختبارات. على سبيل المثال:

generic
   type The_Transfer_Type is private;
   with function Get_Checksummable_Data_Item
           (Msg : The_Transfer_Type;
            I   : Integer) return Integer;
   SIZE : Integer;

package CC_Test_Channel is
   function Checksum(Msg : The_Transfer_Type) return Integer;
end CC_Test_Channel;

الجسد آنذاك:

function Checksum(Msg : The_Transfer_Type) return Integer is
   Sum : Integer := 0;
begin
   -- calculate the checksum
   for i in 1 .. SIZE loop
      Sum := Sum + Get_Checksummable_Data(Msg, I);
   end loop;
   return Sum;
end Checksum;

تكون الوظيفة التي تزودها لـ GET_CHECKSUMMABLE_DATA محددة لـ the_transfer_type وتُرجع ببساطة القيمة المحددة من حقول مكونات the_transfer_type.

هناك عدد من الطرق الأخرى لإعداد هذا أيضًا ، مثل توفير نوع صفيف غير مقيد كمعلمة رسمية عامة ودالة رسمية لاستردادها-وهذا يتيح لك أيضًا التخلص من المعلمة الرسمية ذات الحجم الصريح. أو يمكنك كتابة وظيفة checksum () كواحدة من العمليات على النوع الذي تقوم بتثبيت CC_TEST_CHANNEL معه ، ثم:

with function Calculate_Checksum(Msg : The_Transfer_Type) return Integer;

كواحدة من الرسائل العامة.

التراجع ، وفكر في الاحتمالات ...

نصائح أخرى

(انتقل من تعليق ، حيث أصبح هذا طويلاً)

ADA (95 وما بعده) يدعم التدفقات. على عكس تدفقات C ++ ، والتي هي إلى حد كبير لتحويل السلسلة ، تهدف تدفقات ADA كآلية عامة لأداء العمليات على البيانات (عادة I/O).

كل كائن ADA لديه 'Write و 'Read صفات. هناك بعض التدفقات الموردة للغة (للملف I/O) ، ولكن لديك أيضًا القدرة على إنشاء خاص بك عن طريق الاستخلاص من ada.streams.root_stream_type. إذا كتبت الدفق الخاص بك بهذه الطريقة ، فهناك بعض الإجراءات المنخفضة المستوى التي تمنحك إمكانية الوصول المباشر إلى البيانات.

يتيح لك ذلك كتابة التدفقات الخاصة بك لأداء عمليات مثل I/O ، ضغط البيانات ، أو في حالتك ربما تتحقق من البيانات من الحافلة قبل تحميله في المتغيرات (عبر "قراءة). لقد فعلت ذلك بنفسي في الماضي لتنفيذ وظيفة سجل/تشغيل لبرنامجنا في الوقت الفعلي. نظرت إليه للضغط مرة واحدة أيضًا (انتهى بنا الأمر إلى عدم الحاجة إلى الضغط).

generic 
  type The_Transfer_Type is private; 
  ...

يعني الرمز أعلاه أن العميل يمكنه توفير أي نوع يحلم به من أجل the_transfer_type (طالما أنه ليس "محدودًا"). هذا يعني أيضًا أن عامك العام لا يعرف شيئًا عن هذا النوع ، باستثناء أن الزرع متاح.

مع ADA Generics ، هناك نوع من العلاقة العكسية بين عدد الأنواع المختلفة من الكائنات التي يمكن توفيرها لمعلمة عامة ، وما هي العمليات التي يمكن أن تكون قابلة للإنجاز على تلك الكائنات. على سبيل المثال ، سيكون النوع الأكثر انفتاحًا is limited private. يمكنك توفير أي نوع Whatover لأحد هؤلاء. ومع ذلك ، يمكن أن يفعل العام لا شيء تقريبا معها. حتى المهمة لن تكون متاحة.

خذ "محدودًا" ويمكنك القيام به ، ولكن قد يتم توفير الأنواع التي يمكن تعيينها فقط. من ناحية أخرى ، يمكنك تعريفه على النحو التالي:type The_Transfer_Type is (<>) وبعد ذلك يمكنك توفير أي عدد صحيح أو نوع مرسوم ، وستحصل على أشياء مثل 'first. لا يزال أبعد من ذلك ، يمكنك القيام به type The_Transfer_Type is range <>, ، وستحصل على القدرة على القيام بعمليات الرياضيات الصحيح ، ولكنك ستكون قادرًا فقط على توفير أنواع رقمية عدد صحيح.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top