2011-06-03 21 views
14

Qt dosyasında, altyazılarına kompozisyonlar aracılığıyla alt öğeleri yerleştirebilir miyim, yoksa bunları new ile mi oluşturmalıyım?Qt: Alt nesneler ana nesnesinde oluşturulabilir mi?

class MyWindow : public QMainWindow 
{ 
    ... 
private: 
    QPushButton myButton; 
} 

MyWindow::MyWindow() 
: mybutton("Do Something", this) 
{ 
    ... 
} 

belgeleri üst yok edilir QObject türetilen herhangi bir nesnenin otomatik olarak imha edecektir olduğunu söyler; Bu, yukarıdaki örnekte çakışma olacak olan delete numaralı çağrıya işaret eder.

Aşağıdakileri kullanmak zorunda mıyım?

  • Evet, kompozisyon Tamam:

    QPushButton* myButton; 
    
    myButton = new QPushButton("Do Something", this); 
    

    DÜZENLEME

    cevaplar üç olasılıktan aşağı kaynatın temelde oldukça çeşitlidir ve. ebeveyn aksi üzerinde delete çağırır beri Qt, nesne tahsis edildi anlamaya ve sadece delete yığın-tahsis nesneler (Bu nasıl çalışıyor?)

  • Evet, kompozisyon Tamam, ama bir ebeveyni belirtmeyen edebilirsiniz nesne (Ama bir üst düzey penceresine bir ebeveyn-az Widget dönüş? will not)
  • Hayır daima widget'lardan yığın-tahsis olmak zorunda.

hangisi doğrudur?

cevap

7

statik olmayan, söz konusu nesnenin silme dizisi başladığında olmayan yığın üyesi değişkenleri silinir. Sadece tüm üyeler silindiğinde, temel sınıfın yıkıcısına gider. Bu nedenle, QPushButton myButton üyesi, QMainWindow() çağrılmadan önce silinecektir. Ve QObject belgelerinden: "Bir alt nesneyi ebeveyninden önce silersek, Qt bu nesneyi ebeveynlerin çocuk listesinden otomatik olarak kaldıracaktır". Bu nedenle herhangi bir çarpışma meydana gelmez.

+1

Cevabınız neredeyse doğru, ancak Tahribatın sırası yanlış. Bakınız örn. http://msdn.microsoft.com/en-us/library/8183zf3x%28v=vs.100%29.aspx – hmuelner

+0

@hmuelner Düzeltildi. – Oktalist

2

bir ebeveyn işaretçisi olduğunda nesne sadece imha edilecek, böylece kullanabilirsiniz: QObject onu yok edecek beri

MyWindow::MyWindow() 
: mybutton("Do Something", 0) 
{ 
    ... 
} 
+4

Eğer bir "QWidget" ebeveynsiz ise, en üst düzey bir pencereye dönüşmez mi? –

+0

Evet, bu doğru. Bir QWidget'ın başka bir QWidget'in çocuğu olmasını istiyorsanız, ebeveyne bunu oluşturmak zorundasınız. Ancak, onları, üye değişkenler olarak kullanmanın anlamlı olduğu diğer QObject türetilmiş sınıflar vardır. – hmuelner

+0

-1: Yorumunuz için gerçek cevabınızdan daha fazlası. Diğer insanların işaret ettiği gibi, bir “QObject” ün bir ebeveyn olduğu için yığında olması gereken hiçbir ima yoktur. – Troubadour

0

Sen, yığın üzerinde oluşturmalısınız:

class MyWindow : public QMainWindow 
{ 
    ... 
private: 
    QPushButton *myButton; 
} 

MyWindow::MyWindow() 
: mybutton(new QPushButton("Do Something", this)) 
{ 
    ... 
} 
+0

-1: Diğerlerinin de işaret ettiği gibi, yığın üzerinde oluşturmaya gerek yoktur. – Troubadour

0

çağrı delete Operatör, ur uygulamasını bozmaz, aşağıdaki alıntıları okuyamazsınız, aşağıdaki alıntıları okuyabilirsiniz

QT ebeveyn-çocuk mekanizması QObject'de uygulandı. Bir ebeveyn ile bir nesne (bir widget, doğrulayıcı veya başka bir tür) oluşturduğumuzda, üst öğe nesneyi çocuklarının listesine ekler. Ebeveyn silindiğinde, çocuk listesine girer ve her çocuğu siler. Çocuklar kendileri çocuklarının hepsini siliyorlar, ve böylece hiçbiri kalmayıncaya kadar yinelemeli olarak. Ebeveyn-çocuk mekanizması, bellek yönetimini büyük ölçüde basitleştirir ve bellek sızıntı riskini azaltır. Silme çağrısı yapmamız gereken tek nesne, yeni oluşturduğumuz ve ebeveynleri olmayan nesnelerdir. Ve bir alt nesneyi ebeveyninden önce silersek, Qt bu nesneyi ebeveynlerin çocuk listesinden otomatik olarak kaldırır.

not ebeveyn argüman varsayılan olarak NULL olduğunu (varsayılan argüman) bu QPushButton Oluşturucu

QPushButton (const QString & text, QWidget * parent = 0) 

yüzden u

MyWindow::MyWindow() : mybutton(new QPushButton("Do Something")){ ... } 

kullanabilir ve u herhangi bir bileşeni delete çağırabilir olduğunu ve her zaman

Qt bu po için ilgilenecektir belgeler üst yok edilir QObject türetilen herhangi bir nesnenin otomatik olarak imha söylüyor

4

int; bu bir çağrı O belirli bir varlık yıkıcı ilgili bir çağrı ima

sayılı silmek anlamına gelir.

Örneğinizde, MyWindow'un imha edilmesi durumunda, MyWindow'un yok edicisi çağrıldı demektir. Sırasıyla QPushButton'da uygulanan myButton yıkıcıyı arayacaktır.

Eğer kompozit varlığı varsa

, sadece yıkıcı Bu birim denir ama delete ve bu yüzden kaza olmayacak edilecektir. Qt

Veli çocuk ilişkileri bir yığın veya yığın olması özellikle gerektirmez. Her şeyde olabilir.

bir istif üzerinde üst alt ilişkide benzer bir örnek here üzerindedir.

HTH ..

+2

Ebeveyn, çocuğun yığılı olup olmadığını nasıl anlar? Anladığım kadarıyla, bir yıkıcıyı çağırmak, nesne tarafından kapsanan yığın boşluğunu serbest bırakmaz ('delete' bunun için gereklidir) - yoksa yanılıyor muyum? –

+0

@ Jen, Evet. Eğer 'yeni' diye tahsis edilirse, onu silmeniz gerekir. Uygulamanın çocuğun tahsisini tanımlayabildiği Qt meta nesne sistemi olduğunu düşünüyorum. Bununla ilgili herhangi bir belge bulamadım. Bir şey bulursam güncellenir .. – liaK

+0

@ Jen, Ama çökmez. Bunu denedin mi? Bu dint çarpışma doğru mu? – liaK

4

Object trees & ownership sorunuzu cevaplar. Temel olarak, çocuk nesnesi yığında oluşturulduğunda, üst tarafından silinir. Alt nesne yığını üzerinde oluşturulan Öte yandan

imha sırası önemlidir. Çocuğun ebeveynden önce tahrip edileceği ve kendi ebeveyni listesinden kaldırılacak, böylece tahribatı iki kere aranmaz.

da imha sorunlu sırasını gösteren bu bağlantı bir örnek vardır.

+0

Yani, eğer (yığın veya yığın) kompozitimiz varsa ve (yani "delete" aracılığıyla veya yığın nesnesinin ömrü bittiğinde) imha edilirse, önce kompozitin yıkıcısı çağrılır (ve yapmak istediği her şeyi yapar, ancak kaldırmaz) Bu mantık, QObject içinde uygulandığı için çocuklarından gelen her şeyden sonra, kompozitin çocukları/üyeleri imha edilir (yıkıcıları ile) ve kendilerini hala nesneden (yine QObject işlevselliğini kullanarak) kaldıran şeyden çıkarırlar. QObject'in yıkıcısı nihayet çağrıldı ve hiç çocuk görmüyor - dolayısıyla çift silme yok. – mlvljr

0

Burada sadece quote the source izin verin.

816 QObject::~QObject() 
817 { 
818  Q_D(QObject); 
819  d->wasDeleted = true; 
820  d->blockSig = 0; // unblock signals so we always emit destroyed() 
821 
    ... 
924 
925  if (!d->children.isEmpty()) 
926   d->deleteChildren(); 
927 
928  qt_removeObject(this); 
929 
930  if (d->parent)  // remove it from parent object 
931   d->setParent_helper(0); 
932 
933 #ifdef QT_JAMBI_BUILD 
934  if (d->inEventHandler) { 
935   qWarning("QObject: Do not delete object, '%s', during its event handler!", 
936     objectName().isNull() ? "unnamed" : qPrintable(objectName())); 
937  } 
938 #endif 
939 } 

    ... 

1897 void QObjectPrivate::deleteChildren() 
1898 { 
1899  const bool reallyWasDeleted = wasDeleted; 
1900  wasDeleted = true; 
1901  // delete children objects 
1902  // don't use qDeleteAll as the destructor of the child might 
1903  // delete siblings 
1904  for (int i = 0; i < children.count(); ++i) { 
1905   currentChildBeingDeleted = children.at(i); 
1906   children[i] = 0; 
1907   delete currentChildBeingDeleted; 
1908  } 
1909  children.clear(); 
1910  currentChildBeingDeleted = 0; 
1911  wasDeleted = reallyWasDeleted; 
1912 } 

Yani gördüğünüz gibi, QObject yıkıcı olan çocukların aslında delete her yapar.Ayrıca, destructor herhangi bir üyeden before yıkıcı çalıştırılır; Yani eğer söz konusu bileşik ebeveyne eşitse - o zaman üye QObject, ebeveyninin çocuk listesinden kendisini kaldırma şansına sahip olmayacaktır.

Bu, maalesef, bir QObjectiçine ebeveyn oluşturmak anlamına gelir. Ancak, diğer nesnelere de yazabilir, yığının üstüne tahsis edebilir - nesneyi yok etmeyi garanti ettiğiniz veya ebeveyninnu sıfırlayabilmeniz koşuluyla ebeveyniniz tahrip etmeye başlar.

İlgili konular