-Wmarc.

Marc Mutz pa Qt, Boost, og C ++

Don ikke v re underklasse nar underklasse.

La oss begynne med a se pa noen kode:

En enkel nok klasse. Det fungerer. Vel, teknisk. Hva er a fikse? Anta at noen presenterte denne klassen for deg under kodeanmeldelse. Hva ville du endre? Og hvorfor?

Hvordan riktig subclass QObjects og ikke la dine medprogrammerere rive haret ut.

La forst tenke pa meningen med klassen. Ikke mye tenkning kreves, det star det der:

For det andre: er klassen som lever opp til den hensikt?

La oss handtere problemene igjen.

Mangler Q_OBJECT makro.

Det var en lett en. Vi har alle kommet inn i den ene for, na har vi det? Signaler eller spor som ikke finnes, fungerer.

Likevel kan du fortsatt se den gamle anbefalingen flytende rundt som sier at du bare bor sette Q_OBJECT makroen i klassedisplayet nar du har.

Retningslinje: Nar subclassing QObject (direkte eller indirekte), foretrekker du a legge til Q_OBJECT-makroen, uansett om du ogsa definerer signaler eller spor.

Det er en (sjelden) situasjon der du ikke kan sette inn Q_OBJECT-makroen, og det er nar underkategorien din er en klassemal. Arsaken er at moc bare ikke stotter klassemaler (det er et triks for a fa det til a gjore det, men det har alvorlige begrensninger).

Q_OBJECT-makroen gjor ikke bare signalene og sporene som du definerer pa klassen (i innledende eksempel er det ingen signaler og ingen spor definert pa MyProject :: Label). Det gir en QObject-underklasse sin identitet. Uten den, er Qt, MyProject :: Label bare en QLabel. Ganske bokstavelig: Hvis du skulle sporre en forekomst av MyProject :: Etikett for klassenavnet sitt (ved hjelp av metaObject () -> className ()), ville det faktisk returnere «QLabel & quot; . Vi kan ikke ha dette.

Strengt tatt, dersom hensikten med klassen var a tilby en tilbakekalling for QLabel, sa er det nok at det var akkurat hva klassens forfatter gjorde, i hvert fall sa langt som meta-informasjonen angar. Men nar du introduserer dine egne underklasser, kan du bare sjekke om en gitt widget er av klassen din. Sa, noen darlige vedlikeholdsmedlemmer ville prove a kode slik:

Bare for a se det, ta den andre delen hele tiden. Det gar en harhud & # 8230;

Selvfolgelig burde han ha brukt qobject_cast & lt; MyProject :: Label & gt; (etikett), som ville ha papekt problemet (se respektive Effektive Qt-element). Men hvis han ikke kan endre MyProject :: Label selv, star han fast og venter pa noen som kan lose problemet for ham.

Det er en annen, mer subtil grunn til alltid a legge til makroen: Bakoverkompatibilitet, bin r eller pa annen mate. La oss si at vi hadde samlet alle MyProject-widgets i et bibliotek, og at biblioteket skulle opprettholde bin r kompatibilitet i tvers av utgivelser. Na er det a legge til et spor eller et signal vanligvis bakoverkompatibelt (bin rt eller pa annen mate), de er bare de vanligste medlemsfunksjonene, tross alt, men bare hvis klassen du legger til allerede hadde en Q_OBJECT-makro.

Tenk pa det: Q_OBJECT legger til et statisk statisk QMetaObject staticMetaObject-medlem, hvilke underklassemetobjekter bruker som deres QMetaObject :: superClass (). Moc-verktoyet oppretter denne forbindelsen fra en QObject-underklasse til sin superklasse pa kompileringstidspunktet. Na, hvis noen arver en CoolLabel fra MyProject :: Label, vil CoolLabel :: staticMetaObject.superClass () v re & QLabel :: staticMetaObject. Og det vil forbli pa den maten, selv om MyProject :: Label far sin Q_OBJECT-makro lagt til, med mindre du kjore Moc for CoolLabel igjen, og kompilere.

Med andre ord: Hvis ikke kompilert, vil MyProject :: Label, nar den brukes som en grunnklasse for CoolLabel, ikke kunne finne sine egne (nye) signaler og spor (utenfor sine egne konstruktorer og destruktorer), fordi MyProject :: Etikett: : staticMetaObject, selv om det finnes i MyProject :: Etikett na, hoppes fortsatt over i kjeden fra CoolLabel :: staticMetaObject ned til QLabel :: staticMetaObject.

Manglende konstruktorer / konstruktor argumenter.

Et sikkert tegn pa at du blir komfortabel med et stort klassebibliotek, er nar du begynner a bruke sine klasser uten a forst se pa dokumentasjonen. QLabel er trolig en av de forste Qt-klassene som du vil vite av hjertet # 8221 ;. Sa det er enda mer foruroligende om at denne «# ~» innloseren erstatter & # 8221; av oss har ikke de konstruktorer vi har kommet til a elske pa vare etiketter:

(vi noterer oss i forbifarten at MyProject :: Label-konstruktoren burde v rt eksplisitt ogsa).

Retningslinjer: Foretrekker a tilby alle baseklassekonstruksjoner i underklasser ogsa.

Selv om det er kjedelig arbeid noen ganger (for eksempel nar du arver QTreeWidgetItem): foretrekker a tilby alle konstruktorene til din grunnklasse i din underklasse ogsa. Dette vil gjore det lettere for brukere av klassen a utnytte deres kunnskaper om grunnklassen nar du bruker underklassen.

Retningslinje: Foretrekker a tilby den grunnleggende QObject-konstruktoren (QObject * forelder = 0) nar underklasse QObject s. Gi alltid den grunnleggende QWidget-konstruktoren (QWidget * foreldre = 0, Qt :: WindowFlags f = 0) nar underklasse QWidget.

I tillegg til a hjelpe brukerne med a fa det, er den grunnleggende QWidget-konstruktoren pakrevd av uic, bade for widgets som du gjor tilgjengelig via en Designer-plugin, sa vel som for de som du markedsforer fra en kjent grunnklasse i Designer selv.

Ok, ok. Det er bare halv sannheten. Hva uic krever er en konstruktor som kan kalles med ett QWidget * -argument. Det krever ikke vinduet flagg. Og faktisk har mange QWidget-underklasser (i selve Qt) ikke vinduet flagg. Hvis det er et monster her, har jeg ikke funnet det enda. Hvis du er i tvil, folg den forrige retningslinjen, og gjor som baseklassen din gjor.

Ytterligere konstruksjonsargumenter.

Selv om det ikke gjelder vart forste eksempel som gitt, la vi hore en annen retningslinje, fordi den passer her.

La oss antar at vi vil legge til en ny egenskap Qt :: Orienteringsorientering til vart MyProject :: Etikett, og brukere av etiketten skal kunne sette orienteringen pa konstruksjonstidspunktet. Hvordan ville du endre klassen & # 8217; konstruktorer? Hvilke vil du legge til?

Retningslinje: Foretrekker a folge Qt-konstruktormonsteret: Nar arve QObject s, lister endekonstruktorargument i QObject * foreldre = 0. Nar arve QWidget s, lister sluttkonstruktorargument i QWidget * foreldre = 0, Qt :: WindowFlags f = 0. Legg til flere argumenter i begynnelsen av argumentlisten.

(Du ma ikke markere den siste konstruktoren ovenfor som eksplisitt, men jeg har ikke hort om en kompilator som selv sa mye advare om unodvendig eksplisitt s, sa det gjor ikke vondt for a gjore hver eneste konstruktiv eksplisitt. Faktisk gjor det koden mer robust i mote med endringer, da du legger til et standardargument eller fjerner argumenter, tvinger du ikke til a revurdere beslutningen om a gjore en konstruktor eksplisitt).

Dele denne:

Legg igjen et svar Avbryt svar.

eksplisitt etikett (Qt :: Orientering o, const QString og tekst, QWidget * foreldre = 0, Qt :: WindowFlags f = 0)

Dette trenger ikke a v re eksplisitt, gjor det?

Det bin re kompatibilitetsargumentet for a legge til Q_OBJECT er interessant. Jeg vil si at det er bin rt kompatibelt skjont. En hvilken som helst kode som er kompilert mot pre-Q_OBJECT-biblioteket, vil fremdeles opptre som for, kaller de reimplemented QObject-virtuellene i QLabel og bruker QLabel :: staticMetaObject.

Tilbakekompilere mot etter-Q_OBJECT-versjonen tillater bare koden a bruke feilrettingen av disse reimplementations.

takk for dine kommentarer. Du er selvsagt rett pa begge kontoene selvfolgelig, selv om sporsmalet om hva som bestar av bin r kompatibilitet er noe apen. Selv om det ikke kolliderer, ma det ikke v re bin rt kompatibelt i boken min, men jeg vet ikke hvor noyaktig det er a tegne linjen, heller.

Jeg har tatt med dine kommentarer i artikkelen.

veldig god artikkel. det klargjor noen poeng for meg & # 8230;

Takk for dette innlegget. Jeg er en amator c + + koder og er helt ny i Qt, og jeg har lenge provd a finne god informasjon om beste praksis for underklasse forskjellige Qt-klasser. Dette er det forste jeg har lest, som faktisk gir noe av den informasjonen jeg leter etter.

Jeg har sett mange folk sier (for eksempel pa stackoverflow) at sammensetningen bor foretrekkes over arv, spesielt for klasser som ikke har virtuelle destruktorer (jeg forstar at dette sannsynligvis ikke er et problem nar du arver fra QObject, siden minnet blir styrt).

Forutsatt at dette (sammensetning> arv) er sant, hvordan gjelder denne ideen for ditt eksempel ovenfor? Hvis det ikke er sant, kan du forklare hvorfor? Hvis det avhenger av brukssaken, hvilke retningslinjer bor jeg huske pa nar jeg skriver klassene mine for a avgjore om det skal v re underklasse Qt klasse X eller a inkludere det som medlem?

I oyeblikket prover jeg a skrive et GUI-program for a lage og konvertere finite elementmaskdata til en inngangsfil for et bestemt strukturanalyseprogram. Jeg prover a avgjore om det er fornuftig a underklasse QPointF og QPolygonF i klassene mine Node og Element (Quad, Triangle, Beam, etc etc), eller om jeg skal bruke komposisjon, eller om jeg skal lage mine klasser fra bunnen av.

Beklager det lange sporsmalet. Jeg prover bare a fa en god start pa mitt forste virkelige, egentlige prosjekt som kan bli brukt av noen.

Gjett jeg & # 8217; m en ny komer til QT. Studiet XCode Obj C / Swift en stund for. Har problemer med a subclassere en QLabel fra QT Designer eller Creator i det som et dusin kompilatorfeil. Opprettet min avledede base QLabel klasse .h og .cpp filer som utvider QLabel med bare bare skjelettkode for testing. Deretter kaster du en QLabel til dialogboksen, og kaller den & # 8216; mylabel & # 8217; og markedsfor den til klassenavn & # 8216; Etikett & # 8217 ;. Etter dette trinnet far jeg masse feil som & # 8216; feil: & # 8216; * & # 8217; for & # 8216 ;; & # 8217; & # 8216; og andre i filen ui_formname.h. Ikke sikker pa hva jeg mangler. Jeg har samlet andre apper uten feil, og hvis jeg manuelt legger til QLabel-utvidet klasse, har jeg ikke problemer. Vil bare bruke QT Designer slik at jeg kan se oppsettet.


Vil du spille i det mest populære kasinoet? Vi samlet det for deg. Trykk her nå!