في دلفي 7, لماذا يمكنني تعيين القيمة إلى const?

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

  •  09-06-2019
  •  | 
  •  

سؤال

أنا نسخت بعض دلفي رمز من مشروع إلى آخر ، وجدت أنه لا يجمع في المشروع الجديد ، على الرغم من أنه في القديم.رمز تبدو شيئا مثل هذا:

procedure TForm1.CalculateGP(..)
const
   Price : money = 0;
begin
   ...
   Price := 1.0;
   ...
end;

حتى في المشروع الجديد ، دلفي يشكو من أن "الجانب الأيسر لا يمكن تعيين إلى" - مفهوم!ولكن هذه البرمجية برمجيا في المشروع القديم.لذا سؤالي هو ، لماذا?هل هناك برنامج التحويل البرمجي التبديل للسماح consts أن يكون تكليف ؟ كيف يعمل هذا حتى ؟ ظننت consts استعيض عن قيمها في تجميع الوقت ؟

هل كانت مفيدة؟

المحلول

تحتاج إلى تشغيل احالة كتبته على الثوابت.المشروع -> خيارات -> مترجم -> احالة كتبته الثوابت

أيضا يمكنك إضافة {$J+} أو {$WRITEABLECONST ON} إلى الملف pas, الذي هو على الارجح أفضل ، لأنه سوف يعمل حتى إذا قمت بنقل الملف إلى مشروع آخر.

نصائح أخرى

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

كتبته الثوابت ، من ناحية أخرى ، يمكن أن تكون تنظيما القيم - المصفوفات و السجلات.هؤلاء الرجال بحاجة التخزين الفعلية في تنفيذ أيفإنها تحتاج إلى أن يكون التخزين المخصصة لهم مثل ذلك ، عندما يقوم نظام التشغيل بتحميل الملف القابل للتنفيذ ، قيمة كتبته المستمر ماديا الواردة في الموقع في الذاكرة.

لشرح لماذا تاريخيا كتبته الثوابت في أوائل دلفي و سابقتها, توربو باسكال ، للكتابة (وبالتالي أساسا تهيئة المتغيرات العالمية), نحن بحاجة إلى العودة إلى أيام من دوس.

DOS تشغيل في الوضع الحقيقي ، x86 الشروط.وهذا يعني أن البرامج لديك إمكانية الوصول المباشر إلى الذاكرة الفعلية دون أي MMU القيام الظاهري المادية تعيينات.عندما البرامج لديك إمكانية الوصول المباشر إلى الذاكرة ، أي حماية الذاكرة هو في الواقع.وبعبارة أخرى, إذا كان هناك ذاكرة في أي وقت من العنوان ، هو كل للقراءة وللكتابة في الوضع الحقيقي.

حتى في توربو باسكال برنامج دوس مع كتابة ثابتة القيمة التي يتم تخصيصها على عنوان في الذاكرة في وقت التشغيل ، الذي كتبته ثابت سوف يكون قابل للكتابة.لا يوجد الأجهزة MMU على الطريق و منع البرنامج من الكتابة عليه.وبالمثل, لأن باسكال لا يوجد لديه مفهوم 'const'ness أن C++ ، لا يوجد شيء في نوع النظام لوقف لكم.الكثير من الناس استفادوا من هذا ، منذ توربو باسكال دلفي لم يكن في ذلك الوقت قد تهيئة المتغيرات العالمية كسمة.

الانتقال إلى ويندوز ، هناك طبقة بين عناوين الذاكرة و عناوين:على وحدة إدارة الذاكرة.هذه الشريحة يأخذ فهرس الصفحة (أ إزاحة القناع) من عنوان الذاكرة الذي تحاول الوصول إليه, ويبدو سمات هذه الصفحة في صفحة الجدول.هذه الصفات تشمل للقراءة ، للكتابة ، و الحديثة x86 رقائق غير قابل للتنفيذ الأعلام.مع هذا الدعم ، فمن الممكن أن مارك أقسام .EXE أو .DLL مع سمات مثل التي عند ويندوز لودر تحميل الملف القابل للتنفيذ الصورة في الذاكرة ، فإنه يعين الصفحة المناسبة سمات صفحات الذاكرة التي خريطة القرص صفحات داخل هذه الأقسام.

عندما ويندوز 32 بت نسخة دلفي مترجم أتى وبالتالي فإنه من المنطقي أن تجعل const-مثل الأشياء حقا const ، OS أيضا لديها هذه الميزة.

  1. لماذا:لأن في الإصدارات السابقة من دلفي كتابة الثوابت تم احالة افتراضيا للحفاظ على التوافق مع الإصدارات القديمة حيث كانوا دائما للكتابة (دلفي 1 حتى أوائل باسكال).
    الافتراضي وقد تم الآن تغيير لجعل الثوابت ثابتة حقا...

  2. برنامج التحويل البرمجي التبديل:{$J+} أو {$ي-} {$WRITEABLECONST على} أو {$WRITEABLECONST إيقاف}
    أو في المشروع خيارات المحول البرمجي:تحقق احالة كتبته الثوابت

  3. كيف يعمل:إذا كان المترجم يمكن حساب قيمة في وقت الترجمة ، فإنه يستبدل const من قيمته في كل مكان في التعليمات البرمجية ، وإلا فإنه يحمل مؤشر إلى منطقة الذاكرة القابضة القيمة التي يمكن أن تكون مصنوعة للكتابة أم لا.
  4. انظر 3.

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

  // Example implementation of the Singleton pattern.
  TSingleton = class(TObject)
  protected
    constructor CreateInstance; virtual;
    class function AccessInstance(Request: Integer): TSingleton;
  public
    constructor Create; virtual;
    destructor Destroy; override;
    class function Instance: TSingleton;
    class procedure ReleaseInstance;
  end;

constructor TSingleton.Create;
begin
  inherited Create;

  raise Exception.CreateFmt('Access class %s through Instance only', [ClassName]);
end;

constructor TSingleton.CreateInstance;
begin
  inherited Create;

  // Do whatever you would normally place in Create, here.
end;

destructor TSingleton.Destroy;
begin
  // Do normal destruction here

  if AccessInstance(0) = Self then
    AccessInstance(2);

  inherited Destroy;
end;

{$WRITEABLECONST ON}
class function TSingleton.AccessInstance(Request: Integer): TSingleton;
const
  FInstance: TSingleton = nil;
begin
  case Request of
    0 : ;
    1 : if not Assigned(FInstance) then
          FInstance := CreateInstance;
    2 : FInstance := nil;
  else
    raise Exception.CreateFmt('Illegal request %d in AccessInstance', [Request]);
  end;
  Result := FInstance;
end;
{$IFNDEF WRITEABLECONST_ON}
  {$WRITEABLECONST OFF}
{$ENDIF}

class function TSingleton.Instance: TSingleton;
begin
  Result := AccessInstance(1);
end;

class procedure TSingleton.ReleaseInstance;
begin
  AccessInstance(0).Free;
end;
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top