buni konstruktorni ishga tushirish ro'yxatidan o'tkazish

Quyidagi koddagi ishga tushirish ro'yxatidagi boshqa ob'ektga "bu" ni o'tkazishda muammolar bormi?

class Callback { public: virtual void DoCallback() = 0; }; 

class B
{
    Callback& cb;
public:
    B(Callback& callback) : cb(callback) {}
    void StartThread();

    static void Thread() 
    {
        while (!Shutdown())
        {
            WaitForSomething();
            cb.DoCallback();
        }
     }
};

class A : public Callback
{
    B b;
public:
    A() : b(*this) {b.StartThread();}
    void DoCallback() {} 
};

Agar buni qilish xavfli bo'lsa, eng yaxshi alternativ nima?


c++
person markh44    schedule 15.05.2009    source manba


Javoblar (6)


Agar sizjuda ehtiyot bo'lsangiz bu yaxshi ishlaydi. Agar siz virtual usullarni chaqirishni boshlasangiz yoki turdagi boshqa ob'ektlarga bog'liq usullardan foydalansangiz, siz juda ko'p muammolarga duch kelasiz. Ammo agar siz faqat havola o'rnatayotgan bo'lsangiz, bu yaxshi ishlashi kerak.

Xavfsizroq (lekin to'liq xavfsiz emas) alternativa b ni konstruktor tugallangandan keyin keyinroq o'rnatishdir. Bu muammoli muammolarni bartaraf etmaydi, lekin boshqa a'zo o'zgaruvchilarga ular tuzilishidan oldin kirish kabi muammolarni bartaraf qiladi.

class A : public Callback {
  std::auto_ptr<B> spB;
public:
  A() {
    spB.reset(new B(this));
    spB->StartThread();
  }
};
person JaredPar    schedule 15.05.2009

Agar boshqa sinf sizning holatingiz kabi ko'rsatgichni/ma'lumotnomani saqlasa, u xavfsizdir. Lekin siz this topshirgan konstruktorlar/funksiyalar A konstruktori tugagunga qadar havola qilingan ob'ektga kirishga urinmasligiga ishonch hosil qilishingiz kerak. A ob'ekti hali to'liq qurilmagan va A ni chaqirish usullari va xususiyatlarga kirish aniqlanmagan natijalarga olib kelishi mumkin.

person sth    schedule 15.05.2009

Agar siz ko'rsatgichni keyinroq ishlatish uchun saqlayotgan bo'lsangiz, u odatda xavfsizdir. Men buni qildim. Men quyidagilardan birini qilmayman:

  • Undan asosiy yoki olingan sinf ma'lumotlariga kirish uchun foydalaning (ular konstruktorlarini ishga tushirmagan bo'lishi mumkin)
  • Polimorfik har qanday narsani bajaring, vtable ishga tushirilmasligi mumkin.

Bu yerda C++ tez-tez beriladigan savollardan ajoyib maqola. konstruktorlarda "bu" bilan bog'liq muammolarni batafsil bayon qiladi.

person Doug T.    schedule 15.05.2009
comment
O'sha paytdan va hozirgacha, C++ tez-tez so'raladigan savollarning ajoyib maqolasi bu yerga ko'chirildi. - person peterpi; 28.09.2015

Hali qurilmayotgan ob'ektda kod ishlaydigan konstruktorlarda ish zarrachalarini boshlash xavfli. Siz taqdim etgan kod avvalgidek to'g'ri ishlaydi, ammo yechim mo'rt.

Agar DoCallback A da virtual usulni chaqirsa, ip qanchalik tez ishlashiga qarab siz kutilmagan natijalarga erishishingiz mumkin. Agar chaqirilgan usul sof virtual bo'lsa, dastur o'ladi, agar u sof bo'lmasa, olingan versiya o'rniga usulning A versiyasi chaqiriladi. Aynan shu sababdan hech qachon konstruktordan virtual usulni chaqirmasligingiz kerak.

Ishonchliroq yondashuv bu foydalanuvchiga mavzuni chaqirishdir. Bu shuningdek, boost::thread kutubxonasi va yaqinlashib kelayotgan standartdagi yondashuv. Bajariladigan ob'ektni yarating va ishga tushiring va keyin uni ishlaydigan ish zarrachasiga o'tkazing:

class Worker
{
public:
   void DoWork();
};
void startWorkerThread()
{
   Worker w; // fully create the object that is going to be run before you...
   boost::thread thr( boost::bind( &Worker::DoWork, &w ) ); // ...create thread and run
}
person David Rodríguez - dribeas    schedule 15.05.2009

this ob'ekti hali to'liq qurilmaganligini yodda tutsangiz, bu etarlicha xavfsiz. Agar B sinfingiz konstruktorda undagi funksiyalarni chaqirmasdan shunchaki ko'rsatgichni saqlasa, siz xavfsizsiz. Agar siz B ning konstruktoridan ko'rsatkichga kirishga harakat qilsangiz, juda ehtiyot bo'lishingiz va A a'zolarining ishga tushirilish tartibiga e'tibor berishingiz kerak.

person jalf    schedule 15.05.2009

Malumot to'g'riligiga ishonch hosil qilgan ekansiz, bu double dispatch deb nomlangan idiomaga juda o'xshaydi. Bu holatda ortiqcha bo'lishi mumkin, ammo buning hech qanday yomon joyi yo'q.

person rlbond    schedule 15.05.2009