بشكل عام لإعادة متغير عضو إلى قيمتها الأصلية باستخدام كومة؟

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

  •  03-07-2019
  •  | 
  •  

سؤال

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

وكما تحسن خطرت لي هذا التعميم باستخدام تعريف الفئة الداخلي. هنا هو برنامج سائق عينة (الفئة المرمم).

class Unwind {
private:
  bool b_active_; ///< the thing I want to be restored
  template<typename T>
  class restorer {
    T* ref_;
    T save_;
  public:
    restorer(T* perm) : ref_(perm), save_(*ref_) {};
    ~restorer() { *ref_ = save_; }
  };
public:
  Unwind() : b_active_(false) {};
  void a() { out("a in"); b(); out("a end"); }
  void b() {
    out("b in");
    {
      restorer<bool> trust_in_the_stack(&b_active_); // "restorer" created on the stack
      b_active_ = true; // change b_active_ only while "within" b()
      c();
      out("b inner end");
    }
    out("b end");
  }
  void c() { out("c in"); d(); out("c end"); }
  void d() { out("d in"); cout << "deepest" << endl; out("d end"); }
  void out(const std::string& msg) {
    std::cout << msg << ": " << b_active_ << std::endl;
  }
};

int main() { Unwind u; u.a(); return 0; }

والإخراج باستخدام ز ++ 4.2.3 (سور الصين) هو:

a in: 0
b in: 0
c in: 1
d in: 1
deepest
d end: 1
c end: 1
b inner end: 1
b end: 0
a end: 0

ما هو ما أتوقع في "نهاية ب".

وشعرت أن تعريف المرمم الفئة داخل الطبقة استرخي يساعد على تثبيط سوء الاستخدام.

وسؤالي هو، هل هناك طريقة عامة وأكثر أمانا للقيام بذلك؟ أنا قلق حول قضايا الحياة.

وتحرير: الرجاء نفترض أن هناك أي مواضيع، ولكن "المصب" الأساليب على كومة أن تغيير السلوك على أساس هذا العلم b_active_

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

المحلول 4

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

/// c++ code sample
#ifndef UTIL_RESTORER_HPP
#define UTIL_RESTORER_HPP

namespace Utility {

/// A Restorer instance ("inst") uses the stack to restore a saved
/// value to the named variable when the instance "inst" goes out of
/// scope.
/// 
/// Restorer is designed to be an auto variable, not allocated on any
/// other memory resource like a heap or in-place.
template<typename T>
class restorer {
  T& ref_;
  T  save_;
public:
  restorer(T& perm) : ref_(perm), save_(perm) {}
  ~restorer() { ref_ = save_; }
};

}//NAMESPACE
#endif//UTIL_RESTORER_HPP

نصائح أخرى

وأنا أتفق مع آدم بيرس وأعتقد أيضا أنه يجب تفضل مراجع على مؤشرات:

template<typename T>
class restorer {
   T& ref_;
   T save_;
public:
   restorer(T& perm) : ref_(perm), save_(ref_) {};
   ~restorer() { ref_ = save_; }
};

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

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

وQuantumPete

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