سؤال

في QT أحاول إعداد QWidget الخاص بي ، لذلك يجب أن يعمل كل شيء بشكل جيد بسبب إدارة الذاكرة وأشياء أخرى. لكن لا يبدو لي أن أحصل على كل شيء على ما يرام مع المؤشرات والكومة والمكدس. لدي جهاز MyWidget الخاص بي والذي يحتوي على Qlist مع بعض الكائنات. لا يمكنني معرفة كيفية إعداد كل شيء بشكل صحيح.

يمكنك رؤية الكود الخاص بي أدناه ولدي بعض الأسئلة بخصوص هذا:

  1. يتم إنشاء قائمة متغير Instace على الكومة ، هل سيكون من الأفضل إنشائها على المكدس؟

  2. في قائمتي لدي مؤشرات ، هل من الأفضل إنشاء الكائن على المكدس وإلحاقه بالقائمة؟ (حتى لا يكون لدي مؤشرات في القائمة على الإطلاق)

  3. عندما أقوم بإلحاق الكائنات إلى القائمة ، هل سيحصلون على القائمة كوالدهم تلقائيًا؟ لذلك عندما أقوم بحذف القائمة ، سيتم حذف جميع الكائنات الموجودة داخل القائمة؟

  4. لكل حلقة أحاول استخدامها لا تعمل ، حصلت على "نوع مؤشر/صفيف كان متوقعًا لهذه العملية بدلاً من" int ""

  5. في التعليمات البرمجية الخاصة بي ، أريد إنشاء أجهزة واجهة مستخدمة أخرى تأخذ الكائن من القائمة كمعلمات. هل هي الطريقة الصحيحة للقيام بذلك كما لدي؟ تبدو طريقة مثيل MyOtherWidget هكذا: MyOtherWidget (myobject *myobject ، QWidget *Parent)

شكرا لمساعدتك! أنا جديد على QT و C ++ ، لذا سيكون من الرائع أن توجهني في الاتجاه الصحيح. كيف يمكنني إعداد هذا بالطريقة الصحيحة لتسهيل الأمر ، لا تحصل على تسرب الذاكرة واستخدام القليل من الذاكرة حسب الحاجة. كيف يمكنك إعداد نفس الشيء؟

هذا هو الكود الخاص بي:

mywidget.h:

class MyWidget : public QWidget
{
Q_OBJECT

public:
    MyWidget(QWidget *parent = 0);
    ~MyWidget();

private:
    QList<MyObject*> *list;
};

mywidget.cpp:

MyWidget::MyWidget(QWidget *parent)
{
    ui.setupUi(this);

    list = new QList<MyObject*>();
    for (int i = 0; i<10; i++) 
    {
        MyObject *myObject = new MyObject("Hello",this);
        list->append(myObject);
    }

    foreach(MyObject *myObject, list)
    {
        //Lets say I want to create other widgets here and that they takes a MyObject as a parameter
        MyOtherWidget *myOtherWidget = new MyOtherWidget(myObject,this);
    }

}

MyWidget::~MyWidget(){
    delete list;
}
هل كانت مفيدة؟

المحلول

AD.1. يجب أن يكون عمر القائمة هو نفس عمر مثيل MyWidget ، بحيث يمكنك إنشاء القائمة بأمان على المكدس.

AD.2. يمكنك القيام بذلك ، لكن فئة MyObject تحتاج إلى أن يكون لها مُنشئ افتراضي ومقدم نسخ ومشغل مهمة (انظر http://doc.trolltech.com/4.6/containers.html#container-classes للتفاصيل).

AD.3. لم يتم نقل ملكية الكائن عند إلحاقها. تمامًا مثل حاويات STL ، لا تتصل حاويات QT بحذفها على المؤشرات المخزنة. لحذف جميع المؤشرات المخزنة في Qlist (أو حاوية QT الأخرى) يمكنك استخدام QDeleteall (قائمة). ضع في اعتبارك أنك ربما لا ترغب في القيام بذلك في الكود الذي نشرته: يمكنك تمرير مؤشر MyWidget إلى مُنشئ MyObject وأفترض أنه يتم استخدامه بعد ذلك كوالد Qobject. لذلك سيتم حذف جميع Qobjects عند حذف myWidget.

AD.4. يجب أن تكون الحجة الثانية للماكرو Foreach حاوية ، وليس مؤشرًا للحاوية. لذلك يجب عليك الاتصال بـ foreach (myobject *obj ، *قائمة) إذا كان متغير قائمتك هو مؤشر إلى QList.

AD.5. يجب أن تكون على ما يرام طالما أن myotherWidget لا يحذف myobject المنقولة (لأن mywidget هي بالفعل والد myobject وينتهي بك الأمر إلى حذف نفس الكائن مرتين).

إنه تبسيط جسيم ، ولكن يجب أن تحاول كتابة التعليمات البرمجية الخاصة بك بطريقة لن تحتاج إلى الاتصال بحذفها على الإطلاق. قم بإنشاء أشياء على المكدس أو الاعتماد على آلية الوالدين والوالدين (أي أن الآباء يحذفون أطفالهم). في وقت لاحق ، قد ترغب في قراءة المؤشرات الذكية (QSharedPointer ، QScopedPointer ، إلخ).

تعديل:

سواء تم تعيين والد MyObject أم لا يعتمد على ما تفعله في مُنشئ MyObject. إذا قمت بتمرير وسيطة الوالدين إلى مُنشئ Qobject ، فإن مُنشئ MyObject الخاص بك يبدو مثل هذا:

MyObject(const QString &text, QObject *parent = 0) : QObject(parent)
{
// more code...
}

سيتم تعيين الوالد ، لأنه سيتم القيام به في مُنشئ Qobject ، والذي سيتم استدعاؤه بسبب رمز ": Qobject (Parent)". ماذا لو لم يكن لديك هذا الشظية؟ نظرًا لأن myObject يرث QOBject ، ولا تحدد أي مُنشئ يجب أن يسمى مُنشئ QOBject الافتراضي ، سيتم استدعاء QOBject (QOBJEC تم الحذف.

سأحاول تجنب إعداد الوالدين بشكل صريح من خلال طريقة setParent - لحالات الاستخدام الأساسية ، يجب أن يكون إعداد الوالد في المُنشئ كافيًا.

حاول استخدام المصطلحات الصحيحة (وليس "طريقة مثيل" ، ولكن "مُنشئ") ، وقراءة وثائق QT ، واستخدم الحس السليم وحاول ألا تفكر في أن أي شيء سيتم تلقائيًا. لا يتم تعيين الوالد "تلقائيًا" لمجرد أنك تسمي وسيطة واحدة "الوالد" - تم تعيينها ، لأن هناك قطعة من الكود تقوم بها في مُنشئ Qobject ومسؤوليتك للاتصال بتمرير الوالد إلى مُنشئ Qobject في الفئات التي ترث Qobject.

نصائح أخرى

نعم ، المشكلة هي أنك تحذف كائن قائمتك ولكن ليس عناصرها!

أقترح أن تكون قد ألقيت نظرة على:

QList<Employee *> list;
list.append(new Employee("Blackpool", "Stephen"));
list.append(new Employee("Twist", "Oliver"));

qDeleteAll(list.begin(), list.end());
list.clear();

مزيد من المعلومات هنا

أود أيضًا أن أسأل عما إذا كنت بحاجة حقًا إلى مؤشر إلى قائمتك؟ يمكن أن يكون لديك ببساطة بسيطة:

QList<MyObject*> list;

لذلك لديك تسرب الذاكرة أقل احتمالا!

آمل أن يساعد هذا قليلا !

يحرر :
3. كائنات myobject الخاصة بك لها "هذا" كآباء. القائمة لا تأخذ ملكية الكائنات عندما تتعامل مع المؤشرات.
4. للحلقة ، ربما يجب أن تفكر في التكرار ، وإلقاء نظرة هنا qthelp: //com.trolltech.qt.460/qdoc/qlist.html.

لا تحتاج إلى تخزين عناصر واجهة المستخدم داخل القائمة ، طالما أنك تجعلهم آباء عن القطعة الحالية. (عادةً ما تقوم بإنشاء أجهزة الكمبيوتر الخاصة بك على المكدس مع الجديد).

لدى QT وظيفة التنظيف التلقائي ، مما يعني ، إذا تمت إزالة عنصر واجهة المستخدم جميع عناصر واجهة المستخدم (عناصر واجهة المستخدم التي يتم إزالتها من الوالدين التي تتم إزالة).

لذا فإن الشيء الوحيد الذي سيتعين عليك التأكد منه (خاصة بالنسبة للأدوات المنبثقة المؤقتة) لمحو/إزالة عنصر واجهة المستخدم "المنبثقة" أو مع ذلك تتصل بالملابس المنبثقة.

هذا هو كل شئ.

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