في دلفي 7, لماذا يمكنني تعيين القيمة إلى const?
سؤال
أنا نسخت بعض دلفي رمز من مشروع إلى آخر ، وجدت أنه لا يجمع في المشروع الجديد ، على الرغم من أنه في القديم.رمز تبدو شيئا مثل هذا:
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 حتى أوائل باسكال).
الافتراضي وقد تم الآن تغيير لجعل الثوابت ثابتة حقا...برنامج التحويل البرمجي التبديل:{$J+} أو {$ي-} {$WRITEABLECONST على} أو {$WRITEABLECONST إيقاف}
أو في المشروع خيارات المحول البرمجي:تحقق احالة كتبته الثوابت- كيف يعمل:إذا كان المترجم يمكن حساب قيمة في وقت الترجمة ، فإنه يستبدل const من قيمته في كل مكان في التعليمات البرمجية ، وإلا فإنه يحمل مؤشر إلى منطقة الذاكرة القابضة القيمة التي يمكن أن تكون مصنوعة للكتابة أم لا.
- انظر 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;