QT: Настройка моего собственного Qwidget правильно

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

  •  22-09-2019
  •  | 
  •  

Вопрос

В 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;
}
Это было полезно?

Решение

Объявление Срок службы списка должна быть такой же, как и срок службы экземпляра MyWidget, так что вы можете безопасно создать список в стеке.

Объявление Вы могли бы сделать это, но класс MyObject должен был бы иметь конструктор по умолчанию, конструктор копии и оператор назначения (см. http://doc.trolltech.com/4.6/containers.html#container-classes для получения подробной информации).

Объявление Право собственности на объект не передается в Приложении. Так же, как контейнеры STL, QT Containers не вызывает удаления на сохраненных указателях. Чтобы удалить все указатели, хранящиеся в Qlist (или в другом контейнере QT), вы можете использовать QDeleteAll (список). Имейте в виду, что вы, вероятно, не хотите делать это в опубликованном вами коде: вы передаете указатель MyWidget Constructor, и я предполагаю, что он затем используется в качестве родителя QObject. Таким образом, все цикты будут удалены, когда MyWidget будет удален.

Объявление Вторым аргументом макроса Foreach должен быть контейнер, а не указатель на контейнер. Таким образом, вам следует вызвать Foreach (myObject *obj, *list), если ваша переменная списка является указателем к Qlist.

Объявление У вас все должно быть в порядке, пока Myotherwidget не удаляет пройденный MyObject (потому что MyWidget уже является родителем MyObject, и вы в конечном итоге удалите один и тот же объект дважды).

Это грубое упрощение, но вы должны попытаться написать свой код таким образом, что вам вообще не нужно будет позвонить. Создайте материал в стеке или полагайтесь на механизм родителей QT (то есть родители удаляют своих детей). Позже вы можете прочитать о умных указателях (QsharedPointer, QSCopedPointer и т. Д.).

РЕДАКТИРОВАТЬ:

Будь то родитель MyObject или нет, зависит от того, что вы делаете в конструкторе MyObject. Если вы передаете родительский аргумент конструктору Qobject, то есть ваш конструктор MyObject выглядит так:

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

Родитель будет установлен, потому что это будет сделано в конструкторе Qobject, который будет вызван из -за кода «: Qobject (родитель)». Что если у вас нет этого фрагмента? Поскольку myObject наследует QObject, и вы не указываете, какой конструктор следует назвать конструктором QObject по умолчанию, то есть QObject (QObject *Parent = 0) будет вызван, поэтому родитель вашего MyObject будет нулевым, и он не будет удален.

Я бы старался явно установить родителя с помощью метода 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 имеет функцию Auto-Cleanup, что означает, что если виджет удаляет все детские виджеты (виджеты, родители которых является виджетом, который удаляется) удаляется.

Таким образом, единственное, что вам нужно убедиться (особенно для временных всплывающих виджетов), чтобы стереть/удалить виджет «всплывающее окно» или, как вы называете всплывающий виджет.

Вот и все, вот и все.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top