QT:自分のQWidgetを正しい方法でセットアップする
-
22-09-2019 - |
質問
QTでは、自分のQWidgetをセットアップしようとしているので、メモリ管理などのためにすべてがうまく機能するはずです。しかし、私はポインター、ヒープ、スタックでそれをすべて正しくすることができないようです。いくつかのオブジェクトを備えたQLISTを備えたウィジェットMyWidgetを持っています。すべてを正しくセットアップする方法を理解できません。
以下の私のコードを見ることができますが、これについていくつか質問があります。
Instace変数リストはヒープに作成されていますが、スタックで作成する方が良いでしょうか?
私のリストにはポインターがありますが、スタックにオブジェクトを作成してリストに追加する方が良いでしょうか? (私がリストにまったくポインターを持っていないように)
オブジェクトをリストに追加すると、親が自動的にリストを取得しますか?したがって、リスト内のすべてのオブジェクトを削除すると、削除されますか?
私が使用しようとしている各ループについては機能していません。
私のコードでは、リストからオブジェクトをパラメーターとして取得する他のウィジェットを作成したいと考えています。それは私が持っているようにそれをする正しい方法ですか? 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;
}
解決
広告1。リストの寿命は、MyWidgetインスタンスの寿命と同じである必要があるため、スタック上にリストを安全に作成できます。
広告2。あなたはそれをすることができますが、Myobjectクラスにはデフォルトのコンストラクター、コピーコンストラクター、および割り当てオペレーターが必要です(参照 http://doc.trolltech.com/4.6/containers.html#container-classes 詳細については)。
AD.3。オブジェクトの所有権は付録に転送されません。 STLコンテナと同様に、QTコンテナは、保存されたポインターで削除を呼び出しません。 QLIST(または他のQTコンテナ)に保存されているすべてのポインターを削除するには、QDELETEALL(リスト)を使用できます。心に留めてください、あなたはおそらくあなたが投稿したコードでそれをしたくないことです:あなたはmyobjectコンストラクターにmywidgetポインターを渡し、私はそれがqobjectの親として使用されると思います。したがって、mywidgetが削除されると、すべてのqobjectsが削除されます。
広告4。 foreachマクロの2番目の議論は、コンテナへのポインターではなく、コンテナである必要があります。したがって、リスト変数がQLISTへのポインターである場合、foreach(myobject *obj、 *list)を呼び出す必要があります。
AD.5。 MyOtherwidgetが通過したMyobjectを削除しない限り、問題はありません(MyWidgetはすでにMyobjectの親であり、同じオブジェクトを2回削除することになります)。
それはひどい単純化ですが、削除をまったく呼び出す必要がないようにコードを書くようにしてみてください。スタックに物を作成するか、QT親子メカニズムに依存します(つまり、親は子供を削除します)。後でスマートポインター(QSharedPointer、QScopedPointerなど)について読むことをお勧めします。
編集:
Myobjectの親が設定されているかどうかは、Myobjectコンストラクターで何をしているかに依存します。 QObjectコンストラクターに親の引数を渡すと、myobjectコンストラクターが次のようになります。
MyObject(const QString &text, QObject *parent = 0) : QObject(parent)
{
// more code...
}
親は設定されます。これは、QObjectコンストラクターで行われるため、「:QObject(parent)」コードのために呼び出されます。このフラグメントがない場合はどうなりますか? MyobjectはQobjectを継承し、どのコンストラクターをデフォルトのQobjectコンストラクターと呼ぶべきかを指定していないため、つまりQObject(Qobject *parent = 0)が呼び出されます。削除。
SetParent Methodを使用して親を明示的に設定することを避けようとします - 基本的なユースケースについては、コンストラクターに親を設定するだけで十分です。
正しい用語(「インスタンスメソッド」ではなく「コンストラクター」)を使用し、QTドキュメントを読み、常識を使用して、何でも自動的に行われるとは思わないようにしてください。親は1つの引数「親」と呼ばれるからといって「自動的に」設定されていません - それは設定されています。なぜそれは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;
したがって、メモリリークが1つ少なくなります!
これが少し役立つことを願っています!
編集 :
3. myobjectオブジェクトには、親として「これ」があります。ポインターを扱うとき、リストはオブジェクトの所有権を取得しません。
4.ループについては、繰り返しを検討する必要があります。こちらをご覧ください qthelp://com.trolltech.qt.460/qdoc/qlist.html.
現在のウィジェットの両親にしている限り、子供ウィジェットをリスト内に保存する必要はありません。 (通常、新品でスタックでウィジェットを作成します)。
QTには自動クリーンアップ機能があります。つまり、ウィジェットが削除された場合、すべての子供ウィジェット(親が削除されるウィジェット)が削除されることを意味します。
したがって、(特に一時的なポップアップウィジェットの場合)ウィジェットの「ポップアップ」を消去/削除するか、ポップアップウィジェットを呼び出すことを確認する必要がある唯一のもの。
それだけです、それだけです。