سؤال

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

void func() const
{
     ...
     const_cast<myType*>(myMember) = new myType();
     ...
}

يعمل هذا بشكل جيد في VC ++ ، لكن GCC يعطي خطأً في الرسالة "LVALUE مطلوب كمعامل رئيسي من المهمة".

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

هل يمكنني تعيين عضوي دون الحاجة إلى جعل العضو قابلاً للتغيير؟ كيف؟ هل هناك أي آثار جانبية في جعل الأعضاء قابلة للتغيير؟

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

المحلول

لن يعمل الكود فعليًا في VC ++ - أنت لا تقوم بتحديث القيمة (أو على الأقل لا ينبغي) ، وبالتالي التحذير من GCC. الكود الصحيح هو

const_cast<myType*&>(myMember) = new myType();

أو [من الرد الآخر ، شكرًا: P]:

const_cast<ThisType*>(this)->myMember = new myType();

مما يجعلها قابلة للتغيير بشكل فعال أنك تصبح ضمنيًا const_castS في const وظائف الأعضاء ، وهو ما يجب أن توجه إليه بشكل عام عندما تجد نفسك تقوم بأحمال const_castS على this. لا توجد "آثار جانبية لاستخدام قابلة للتغيير" بخلاف ذلك.

كما ترون من المناقشات الشديدة التي تدور حول هذا السؤال ، فإن الاستخدام اللطيف mutable والكثير من const_castيمكن أن تكون S بالتأكيد أعراض رائحة سيئة في الكود الخاص بك. من وجهة نظر مفاهيمية أو إبعاد القدة أو استخدامها mutable يمكن أن يكون لها آثار أكبر بكثير. في بعض الحالات ، قد يكون الشيء الصحيح الذي يجب القيام به هو تغيير الطريقة إلى غير المحتملين ، أي امتلاك حقيقة أنها تعدل الحالة.

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

نصائح أخرى

هذا السيناريو - تغيير الحالة الداخلية المغلفة لا يؤثر على الحالة الخارجية (مثل نتائج التخزين المؤقت) - هو بالضبط ما mutable الكلمة الرئيسية ل.

const_cast هو دائما تقريبا علامة على فشل التصميم. في مثالك ، إما func() لا ينبغي أن يكون const, ، أو myMember يجب ان يكون mutable.

المتصل func() ستتوقع أن لا يتغير هدفها ؛ لكن هذا يعني "عدم التغيير بطريقة يمكن أن تلاحظها" ؛ هذا ، ليس لتغيير حالته الخارجية. إذا تغير myMember لا يغير الحالة الخارجية للكائن ، وهذا ما mutable الكلمة الرئيسية ل ؛ غير ذلك، func() لا ينبغي أن يكون const, ، لأنك ستخون ضمانات وظيفتك.

تذكر ذلك mutable ليست آلية لتصحيح circunvent. إنها آلية لتحسينه.

class Class{
int value;
void func()const{
const_cast<Class*>(this)->value=123;
}
};

كما كتب ستيف جيلهام ، mutable هو الإجابة الصحيحة (وقصيرة) على سؤالك. أريد فقط أن أعطيك تلميحًا في اتجاه مختلف. ربما يكون من الممكن في Szenario استخدام واجهة (أو أكثر من واحد)؟ ربما يمكنك تجويفه من المثال التالي:

class IRestrictedWriter // may change only some members
{
public:
  virtual void func() = 0; 
}

class MyClass : virtual public IRestrictedWriter
{
public:
  virtual void func()
  {
    mValueToBeWrittenFromEverybody = 123; 
  }

  void otherFunctionNotAccessibleViaIRestrictedWriter()
  {
    mOtherValue1 = 123;
    mOtherValue2 = 345;
  }

  ...   
}

لذا ، إذا انتقلت إلى بعض الوظائف IRestrictedReader * بدل من const MyClass * يمكن أن يتصل func وبالتالي التغيير mValueToBeWrittenFromEverybody بينما mOtherValue1 هو نوع من "const".

. وجدت mutable دائما قليلا من الاختراق (ولكن استخدمه في بعض الأحيان).

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