سؤال

بالنسبة لأحد مشاريعي ، لدي شجرة من الكائنات المشتقة من Qobject ، والتي تستخدم وظائف الوالدين/الطفل في Qobject لبناء الشجرة.

هذا مفيد للغاية ، لأنني أستفيد من الإشارات والفتحات ، استخدم مؤشرات QT الحراسة وتتوقع أن تحذف كائنات الوالدين الأطفال عند حذفهم.

حتى الان جيدة جدا. للأسف الآن ، يتطلب مني مشروعي إدارة/تغيير ترتيب الأطفال. لا توفر Qobject أي وسيلة لتغيير ترتيب أطفالها (استثناء: وظيفة QWidget's Rise () - ولكن هذا عديمة الفائدة في هذه الحالة). الآن أنا أبحث عن استراتيجية للسيطرة على ترتيب الأطفال. كان لدي بعض الأفكار ، لكنني لست متأكدًا من إيجابياتهم وسلبياتهم:



الخيار أ: متغير عضو فهرس فرز مخصص

إستخدم int m_orderIndex متغير العضو كمفتاح فرز وقدم أ sortedChildren() الطريقة التي تُرجع قائمة من Qobjects مرتبة بواسطة هذا المفتاح.

  • سهل التنفيذ في بنية الكائن الحالية.
  • مشكلة متى QObject::children() يتم تجاوز الطريقة - ستؤدي إلى مشكلات خلال الحلقات عند تغيير ترتيب العناصر ، وأيضًا أغلى من التنفيذ الافتراضي.
  • يجب أن تعود إلى ترتيب كائن Qobject إذا كانت جميع مفاتيح الفرز متساوية أو 0/افتراضي.

الخيار ب: قائمة زائدة من الأطفال

الحفاظ على قائمة زائدة من الأطفال في أ QList, ، وأضف الأطفال إليها عند إنشائها وتدميرها.

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

الخيار ج: ...؟

أي أفكار أو ردود فعل ، وخاصة من الأشخاص الذين حلوا هذا بالفعل في مشاريعهم الخاصة ، موضع تقدير كبير. سنة جديدة سعيدة!

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

المحلول

قضيت الكثير من الوقت في مرور كل هذه الخيارات في الأيام الماضية وناقشتها بعناية مع بعض المبرمجين الآخرين. قررنا الذهاب ل الخيار أ.

كل من الكائنات التي نديرها هي طفل كائن الوالدين. نظرًا لأن QT لا توفر أي وسيلة لإعادة طلب هذه الكائنات ، فقد قررنا إضافة أ int m_orderIndex خاصية لكل كائن ، والتي تتخلف عن 0.

كل كائن لديه وظيفة ملحق sortedChildren() الذي يعيد أ QObjectList من الأطفال. ما نفعله في هذه الوظيفة هو:

  1. استخدم العادي QObject::chilren() وظيفة للحصول على قائمة بجميع كائنات الأطفال المتاحة.
  2. dynamic_cast جميع الكائنات إلى "الفئة الأساسية" الخاصة بنا ، والتي توفر m_orderIndex منشأه.
  3. إذا كان الكائن قابلاً للتصوير ، فأضفه إلى قائمة كائن مؤقتة.
  4. استعمال qSort مع العرف LessThan وظيفة لمعرفة ما إذا كان QSort يحتاج إلى تغيير ترتيب كائنين.
  5. إرجاع قائمة الكائن المؤقتة.

لقد فعلنا هذا للأسباب التالية:

  • يمكن الاستمرار في التعليمات البرمجية الحالية (وخاصة الكود الخاص بـ QT) children() دون الحاجة إلى القلق بشأن الآثار الجانبية.
  • يمكننا استخدام العادي children() الوظيفة في الأماكن التي لا يهم الطلب فيها ، دون أن يكون هناك أي خسارة في الأداء.
  • في الأماكن التي نحتاج فيها إلى قائمة الأطفال المطلوبة ، نستبدل ببساطة children() بواسطة sortedChildren() والحصول على التأثير المطلوب.

أحد الأشياء الجيدة في هذا النهج هو أن ترتيب الأطفال لا يتغير إذا تم ضبط جميع مؤشرات الفرز على الصفر.

آسف للإجابة على سؤالي ، آمل أن ينير الناس بنفس المشكلة. ؛)

نصائح أخرى

ماذا عن شيء مثل ...

  1. Qlist listchildren = (qlist) children () ؛
  2. فرز Listchildren
  3. foreach listchildren setParent (tempparent)
  4. foreach listchildren setParent (OriginalParent)

اختراق سيء: qobject :: الأطفال () إرجاع مرجع إلى const. هل يمكن أن تخلص من الوفرة وبالتالي التلاعب بالقائمة الداخلية مباشرة.

هذا شرير إلى حد ما ، وله خطر إبطال المتكررين الذين يحتفظ بهم Qobject داخليًا.

ليس لدي خيار منفصل C ، ولكن مقارنة الخيار A و B ، فأنت تتحدث ~ 4 بايت (مؤشر 32 بت ، عدد صحيح 32 بت) في كلتا الحالتين ، لذلك سأذهب مع الخيار B ، حيث يمكنك الاحتفاظ هذه القائمة مرتبة.

لتجنب التعقيد الإضافي لتتبع الأطفال ، يمكنك الغش والحفاظ على قائمتك مرتبة ومرتبة ، ولكن الجمع بينها مع طريقة فرز الأطفال تقوم بتصفية جميع غير الأطفال. التعقيد الحكيم ، هذا ينتهي به المطاف حول O (nlogm) (n = الأطفال ، m = القائمة إدخالات ، على افتراض أن m> = n ، أي أن الأطفال يضافون دائمًا) ما لم يكن لديك تحول كبير على الأطفال. دعنا نسمي هذا الخيار C.

Quicksort ، في الخيار المقترح الخاص بك ، يمنحك O (N2) (WC) ، ولكن يتطلب منك أيضًا أن تكون مؤشرات مستردة ، وتتبعها ، وتردد عدد صحيح ، وما إلى ذلك. (ن)).

لقد واجهت نفس المشكلة وحلتها حسب الخيار B. التتبع ليس بهذه الصعوبة ، فقط قم بإنشاء طريقة "void addchild (type *ptr) ؛" وواحد آخر لحذف الطفل.

أنت لا تعاني من التكرار الشرير إذا قمت بتخزين الأطفال حصريًا داخل قائمة الطفل الخاصة/العامة (Qlist) لكل عنصر وإسقاط قاعدة Qobject. في الواقع من السهل جدًا تنفيذ Auto-Chilp مجانًا (على الرغم من أن ذلك يتطلب مؤشرًا إضافيًا للوالدين).

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