Jump to content
Main menu
Main menu
move to sidebar
hide
Navigation
Home
Help
Recent changes
Contributor Help Pages
Tasks and Tools
Modify a page
Add new content
Page elements
Typographical guidelines
More markup help
Translator Help Pages
Get a Translator Account
Languages represented
Translation Workflow
Translate a Page
Off-line Translation
Translation Statistics
More Help pages
Search
Search
English
Log in
Personal tools
Log in
Export translations
Translate
English
Language statistics
Message group statistics
Export
Tools
Tools
move to sidebar
hide
Actions
Language statistics
Message group statistics
Export
General
Special pages
Printable version
Settings
Group
Category:Phonon
Contribute/List of KDE Modules
Development
Development/FAQs/General FAQ
Development/FAQs/Technical FAQ
Development/KDevelop-PG-Qt Introduction
Development/Tools
Development/Tutorials
Development/Tutorials/CommandLineArguments
Development/Tutorials/Common Programming Mistakes
Development/Tutorials/First program
Development/Tutorials/First program/KDE4
Development/Tutorials/First program/KF5
Development/Tutorials/KDE3/Qt Designer and KDevelop 3.0 for Beginners
Development/Tutorials/Metadata/Nepomuk/TipsAndTricks
Development/Tutorials/Physical Simulation
Development/Tutorials/Qt4 Ruby Tutorial
Development/Tutorials/Qt4 Ruby Tutorial/Chapter 01
Development/Tutorials/Qt4 Ruby Tutorial/Chapter 04
Development/Tutorials/Qt4 Ruby Tutorial/Chapter 05
Development/Tutorials/Qt4 Ruby Tutorial/Chapter 06
Development/Tutorials/Qt4 Ruby Tutorial/Chapter 07
Development/Tutorials/Qt4 Ruby Tutorial/Chapter 08
Development/Tutorials/Qt4 Ruby Tutorial/Chapter 09
Development/Tutorials/Qt4 Ruby Tutorial/Chapter 10
Development/Tutorials/Qt4 Ruby Tutorial/Chapter 11
Development/Tutorials/Qt4 Ruby Tutorial/Chapter 12
Development/Tutorials/Qt4 Ruby Tutorial/Chapter 13
Development/Tutorials/Qt4 Ruby Tutorial/Chapter 14
Development/Tutorials/Qt4 Ruby Tutorial/Chapter 2
Development/Tutorials/Qt4 Ruby Tutorial/Chapter 3
Development/Tutorials/Saving and loading
Development/Tutorials/Setting Up
Development/Tutorials/Using Actions
Development/Tutorials/Using KXmlGuiWindow
Documentation Primer
Edit Markup
Getting Started
Help:Contents
Help:Contribute
How To Convert a UserBase Manual to Docbook
KDE Frameworks
KDE Frameworks/Getting Started
KDE TechBase:About
KDE TechBase:Contributors
KDE TechBase:General disclaimer
KDE TechBase:Privacy policy
Off-line Translation
Projects/Calligra/Plugin Tutorials
Toolbox
Translate a Page
Translation Workflow
Typographical Guidelines
User:Neverendingo
Welcome to KDE TechBase
Language
aa - Afar
ab - Abkhazian
abs - Ambonese Malay
ace - Achinese
acm - Iraqi Arabic
ady - Adyghe
ady-cyrl - Adyghe (Cyrillic script)
aeb - Tunisian Arabic
aeb-arab - Tunisian Arabic (Arabic script)
aeb-latn - Tunisian Arabic (Latin script)
af - Afrikaans
aln - Gheg Albanian
alt - Southern Altai
am - Amharic
ami - Amis
an - Aragonese
ang - Old English
ann - Obolo
anp - Angika
ar - Arabic
arc - Aramaic
arn - Mapuche
arq - Algerian Arabic
ary - Moroccan Arabic
arz - Egyptian Arabic
as - Assamese
ase - American Sign Language
ast - Asturian
atj - Atikamekw
av - Avaric
avk - Kotava
awa - Awadhi
ay - Aymara
az - Azerbaijani
azb - South Azerbaijani
ba - Bashkir
ban - Balinese
ban-bali - Balinese (Balinese script)
bar - Bavarian
bbc - Batak Toba
bbc-latn - Batak Toba (Latin script)
bcc - Southern Balochi
bci - Baoulé
bcl - Central Bikol
bdr - West Coast Bajau
be - Belarusian
be-tarask - Belarusian (Taraškievica orthography)
bew - Betawi
bg - Bulgarian
bgn - Western Balochi
bh - Bhojpuri
bho - Bhojpuri
bi - Bislama
bjn - Banjar
blk - Pa'O
bm - Bambara
bn - Bangla
bo - Tibetan
bpy - Bishnupriya
bqi - Bakhtiari
br - Breton
brh - Brahui
bs - Bosnian
btm - Batak Mandailing
bto - Iriga Bicolano
bug - Buginese
bxr - Russia Buriat
ca - Catalan
cbk-zam - Chavacano
cdo - Min Dong Chinese
ce - Chechen
ceb - Cebuano
ch - Chamorro
cho - Choctaw
chr - Cherokee
chy - Cheyenne
ckb - Central Kurdish
co - Corsican
cps - Capiznon
cpx - Pu-Xian Min
cpx-hans - Pu-Xian Min (Simplified Han script)
cpx-hant - Pu-Xian Min (Traditional Han script)
cpx-latn - Pu-Xian Min (Latin script)
cr - Cree
crh - Crimean Tatar
crh-cyrl - Crimean Tatar (Cyrillic script)
crh-latn - Crimean Tatar (Latin script)
crh-ro - Crimean Tatar (Romania)
cs - Czech
csb - Kashubian
cu - Church Slavic
cv - Chuvash
cy - Welsh
da - Danish
dag - Dagbani
de - German
de-at - Austrian German
de-ch - Swiss High German
de-formal - German (formal address)
dga - Dagaare
din - Dinka
diq - Zazaki
dsb - Lower Sorbian
dtp - Central Dusun
dty - Doteli
dv - Divehi
dz - Dzongkha
ee - Ewe
egl - Emilian
el - Greek
eml - Emiliano-Romagnolo
en - English
en-ca - Canadian English
en-gb - British English
eo - Esperanto
es - Spanish
es-419 - Latin American Spanish
es-formal - Spanish (formal address)
et - Estonian
eu - Basque
ext - Extremaduran
fa - Persian
fat - Fanti
ff - Fula
fi - Finnish
fit - Tornedalen Finnish
fj - Fijian
fo - Faroese
fon - Fon
fr - French
frc - Cajun French
frp - Arpitan
frr - Northern Frisian
fur - Friulian
fy - Western Frisian
ga - Irish
gaa - Ga
gag - Gagauz
gan - Gan Chinese
gan-hans - Gan (Simplified)
gan-hant - Gan (Traditional)
gcr - Guianan Creole
gd - Scottish Gaelic
gl - Galician
gld - Nanai
glk - Gilaki
gn - Guarani
gom - Goan Konkani
gom-deva - Goan Konkani (Devanagari script)
gom-latn - Goan Konkani (Latin script)
gor - Gorontalo
got - Gothic
gpe - Ghanaian Pidgin
grc - Ancient Greek
gsw - Alemannic
gu - Gujarati
guc - Wayuu
gur - Frafra
guw - Gun
gv - Manx
ha - Hausa
hak - Hakka Chinese
haw - Hawaiian
he - Hebrew
hi - Hindi
hif - Fiji Hindi
hif-latn - Fiji Hindi (Latin script)
hil - Hiligaynon
hno - Northern Hindko
ho - Hiri Motu
hr - Croatian
hrx - Hunsrik
hsb - Upper Sorbian
hsn - Xiang Chinese
ht - Haitian Creole
hu - Hungarian
hu-formal - Hungarian (formal address)
hy - Armenian
hyw - Western Armenian
hz - Herero
ia - Interlingua
id - Indonesian
ie - Interlingue
ig - Igbo
igl - Igala
ii - Sichuan Yi
ik - Inupiaq
ike-cans - Eastern Canadian (Aboriginal syllabics)
ike-latn - Eastern Canadian (Latin script)
ilo - Iloko
inh - Ingush
io - Ido
is - Icelandic
it - Italian
iu - Inuktitut
ja - Japanese
jam - Jamaican Creole English
jbo - Lojban
jut - Jutish
jv - Javanese
ka - Georgian
kaa - Kara-Kalpak
kab - Kabyle
kai - Karekare
kbd - Kabardian
kbd-cyrl - Kabardian (Cyrillic script)
kbp - Kabiye
kcg - Tyap
kea - Kabuverdianu
kg - Kongo
khw - Khowar
ki - Kikuyu
kiu - Kirmanjki
kj - Kuanyama
kjh - Khakas
kjp - Eastern Pwo
kk - Kazakh
kk-arab - Kazakh (Arabic script)
kk-cn - Kazakh (China)
kk-cyrl - Kazakh (Cyrillic script)
kk-kz - Kazakh (Kazakhstan)
kk-latn - Kazakh (Latin script)
kk-tr - Kazakh (Turkey)
kl - Kalaallisut
km - Khmer
kn - Kannada
ko - Korean
ko-kp - Korean (North Korea)
koi - Komi-Permyak
kr - Kanuri
krc - Karachay-Balkar
kri - Krio
krj - Kinaray-a
krl - Karelian
ks - Kashmiri
ks-arab - Kashmiri (Arabic script)
ks-deva - Kashmiri (Devanagari script)
ksh - Colognian
ksw - S'gaw Karen
ku - Kurdish
ku-arab - Kurdish (Arabic script)
ku-latn - Kurdish (Latin script)
kum - Kumyk
kus - Kʋsaal
kv - Komi
kw - Cornish
ky - Kyrgyz
la - Latin
lad - Ladino
lb - Luxembourgish
lbe - Lak
lez - Lezghian
lfn - Lingua Franca Nova
lg - Ganda
li - Limburgish
lij - Ligurian
liv - Livonian
lki - Laki
lld - Ladin
lmo - Lombard
ln - Lingala
lo - Lao
loz - Lozi
lrc - Northern Luri
lt - Lithuanian
ltg - Latgalian
lus - Mizo
luz - Southern Luri
lv - Latvian
lzh - Literary Chinese
lzz - Laz
mad - Madurese
mag - Magahi
mai - Maithili
map-bms - Basa Banyumasan
mdf - Moksha
mg - Malagasy
mh - Marshallese
mhr - Eastern Mari
mi - Māori
min - Minangkabau
mk - Macedonian
ml - Malayalam
mn - Mongolian
mnc - Manchu
mnc-latn - Manchu (Latin script)
mnc-mong - Manchu (Mongolian script)
mni - Manipuri
mnw - Mon
mo - Moldovan
mos - Mossi
mr - Marathi
mrh - Mara
mrj - Western Mari
ms - Malay
ms-arab - Malay (Jawi script)
mt - Maltese
mus - Muscogee
mwl - Mirandese
my - Burmese
myv - Erzya
mzn - Mazanderani
na - Nauru
nah - Nāhuatl
nan - Min Nan Chinese
nap - Neapolitan
nb - Norwegian Bokmål
nds - Low German
nds-nl - Low Saxon
ne - Nepali
new - Newari
ng - Ndonga
nia - Nias
niu - Niuean
nl - Dutch
nl-informal - Dutch (informal address)
nmz - Nawdm
nn - Norwegian Nynorsk
no - Norwegian
nod - Northern Thai
nog - Nogai
nov - Novial
nqo - N’Ko
nrm - Norman
nso - Northern Sotho
nv - Navajo
ny - Nyanja
nyn - Nyankole
nys - Nyungar
oc - Occitan
ojb - Northwestern Ojibwa
olo - Livvi-Karelian
om - Oromo
or - Odia
os - Ossetic
pa - Punjabi
pag - Pangasinan
pam - Pampanga
pap - Papiamento
pcd - Picard
pcm - Nigerian Pidgin
pdc - Pennsylvania German
pdt - Plautdietsch
pfl - Palatine German
pi - Pali
pih - Norfuk / Pitkern
pl - Polish
pms - Piedmontese
pnb - Western Punjabi
pnt - Pontic
prg - Prussian
ps - Pashto
pt - Portuguese
pt-br - Brazilian Portuguese
pwn - Paiwan
qu - Quechua
qug - Chimborazo Highland Quichua
rgn - Romagnol
rif - Riffian
rki - Arakanese
rm - Romansh
rmc - Carpathian Romani
rmy - Vlax Romani
rn - Rundi
ro - Romanian
roa-tara - Tarantino
rsk - Pannonian Rusyn
ru - Russian
rue - Rusyn
rup - Aromanian
ruq - Megleno-Romanian
ruq-cyrl - Megleno-Romanian (Cyrillic script)
ruq-latn - Megleno-Romanian (Latin script)
rw - Kinyarwanda
ryu - Okinawan
sa - Sanskrit
sah - Yakut
sat - Santali
sc - Sardinian
scn - Sicilian
sco - Scots
sd - Sindhi
sdc - Sassarese Sardinian
sdh - Southern Kurdish
se - Northern Sami
se-fi - Northern Sami (Finland)
se-no - Northern Sami (Norway)
se-se - Northern Sami (Sweden)
sei - Seri
ses - Koyraboro Senni
sg - Sango
sgs - Samogitian
sh - Serbo-Croatian
sh-cyrl - Serbo-Croatian (Cyrillic script)
sh-latn - Serbo-Croatian (Latin script)
shi - Tachelhit
shi-latn - Tachelhit (Latin script)
shi-tfng - Tachelhit (Tifinagh script)
shn - Shan
shy - Shawiya
shy-latn - Shawiya (Latin script)
si - Sinhala
simple - Simple English
sjd - Kildin Sami
sje - Pite Sami
sk - Slovak
skr - Saraiki
skr-arab - Saraiki (Arabic script)
sl - Slovenian
sli - Lower Silesian
sm - Samoan
sma - Southern Sami
smn - Inari Sami
sms - Skolt Sami
sn - Shona
so - Somali
sq - Albanian
sr - Serbian
sr-ec - српски (ћирилица)
sr-el - srpski (latinica)
srn - Sranan Tongo
sro - Campidanese Sardinian
ss - Swati
st - Southern Sotho
stq - Saterland Frisian
sty - Siberian Tatar
su - Sundanese
sv - Swedish
sw - Swahili
syl - Sylheti
szl - Silesian
szy - Sakizaya
ta - Tamil
tay - Tayal
tcy - Tulu
tdd - Tai Nuea
te - Telugu
tet - Tetum
tg - Tajik
tg-cyrl - Tajik (Cyrillic script)
tg-latn - Tajik (Latin script)
th - Thai
ti - Tigrinya
tk - Turkmen
tl - Tagalog
tly - Talysh
tly-cyrl - Talysh (Cyrillic script)
tn - Tswana
to - Tongan
tok - Toki Pona
tpi - Tok Pisin
tr - Turkish
tru - Turoyo
trv - Taroko
ts - Tsonga
tt - Tatar
tt-cyrl - Tatar (Cyrillic script)
tt-latn - Tatar (Latin script)
tum - Tumbuka
tw - Twi
ty - Tahitian
tyv - Tuvinian
tzm - Central Atlas Tamazight
udm - Udmurt
ug - Uyghur
ug-arab - Uyghur (Arabic script)
ug-latn - Uyghur (Latin script)
uk - Ukrainian
ur - Urdu
uz - Uzbek
uz-cyrl - Uzbek (Cyrillic script)
uz-latn - Uzbek (Latin script)
ve - Venda
vec - Venetian
vep - Veps
vi - Vietnamese
vls - West Flemish
vmf - Main-Franconian
vmw - Makhuwa
vo - Volapük
vot - Votic
vro - Võro
wa - Walloon
wal - Wolaytta
war - Waray
wls - Wallisian
wo - Wolof
wuu - Wu Chinese
wuu-hans - Wu Chinese (Simplified)
wuu-hant - Wu Chinese (Traditional)
xal - Kalmyk
xh - Xhosa
xmf - Mingrelian
xsy - Saisiyat
yi - Yiddish
yo - Yoruba
yrl - Nheengatu
yue - Cantonese
yue-hans - Cantonese (Simplified)
yue-hant - Cantonese (Traditional)
za - Zhuang
zea - Zeelandic
zgh - Standard Moroccan Tamazight
zh - Chinese
zh-cn - Chinese (China)
zh-hans - Simplified Chinese
zh-hant - Traditional Chinese
zh-hk - Chinese (Hong Kong)
zh-mo - Chinese (Macau)
zh-my - Chinese (Malaysia)
zh-sg - Chinese (Singapore)
zh-tw - Chinese (Taiwan)
zu - Zulu
qqq - Message documentation
Format
Export for off-line translation
Export in native format
Export in CSV format
Fetch
{{DISPLAYTITLE:Desenvolvimento/Tutoriais/Erros Comuns de Programação}}<languages/> {{TutorialBrowser| series=Iniciando| name=Erros Comuns de Programação| reading=[[Policies/API_to_Avoid|APIs to avoid]] }} <span id="Abstract"></span> == Resumo == Este tutorial tem como objetivo combinar a experiência dos desenvolvedores KDE em relação aos prós e contras dos frameworks Qt e KDE. Além de erros reais, ele também cobre coisas que não são necessariamente "bugs", mas que tornam o código mais lento ou menos legível. <span id="General_C++"></span> == C ++ em geral == Esta seção te guia por alguns dos cantos mais empoeirados do C ++ que tende a ser mal utilizado ou que as pessoas também simplesmente erram. === Anonymous namespaces vs statics === Se você possui um método em uma classe que não acessa nenhum membro e, portanto, não precisa de um objeto para operar, torne-o estático. Se, além disso, for uma função auxiliar privada que não é necessária fora do arquivo, torne-a uma função estática do arquivo. Isso esconde o símbolo completamente. Os símbolos definidos em um anonymous namespace C++ não têm ligação interna. Os anonymous namespaces fornecem apenas um nome exclusivo para essa unidade de tradução e é isso; eles não alteram a ligação do símbolo. A ligação não é alterada naquelas porque a segunda fase da pesquisa de nome em duas fases ignora as funções com ligações internas. Além disso, entidades com ligação interna não podem ser usadas como argumentos de template. Portanto, dessa vez, ao invés de usar anonymous namespaces, use static se você não quiser que um símbolo seja exportado. <span id="NULL_pointer_issues"></span> === Problemas de ponteiro NULL === Em primeiro lugar: tudo bem excluir um ponteiro nulo. Portanto, construções como esta que verificam se há nulo antes de excluir são simplesmente redundantes: <syntaxhighlight lang="cpp-qt"> if ( ptr ) { delete ptr; } </syntaxhighlight> Observe, no entanto, que '''a null check ''é'' necessária quando você exclui uma matriz''' - isso ocorre porque um compilador relativamente recente no Solaris não lida com isso adequadamente. Ao excluir um ponteiro, certifique-se de defini-lo também como 0, para que futuras tentativas de excluir esse objeto não falhem em uma exclusão dupla. Portanto, a maneira completa e adequada é: <syntaxhighlight lang="cpp-qt"> delete ptr; ptr = 0; </syntaxhighlight> Você pode perceber que ponteiros nulos são variavelmente marcados em uma das quatro maneiras: 0, 0L, NULL e nullptr. Em C, NULL é definido como um ponteiro void. No C ++, é possível maior segurança devido a uma verificação mais rigorosa de tipo. As implementações modernas do C++11 (e todas as implementações do C++14) definem NULL para igual ao valor especial nullptr. Nullptr pode ser convertido automaticamente para booleano false, mas uma conversão para um tipo inteiro falhará. Isso é útil para evitar acidentes. As implementações mais antigas do C++ anteriores ao c++11 simplesmente definiam NULL como 0L ou 0, o que não fornece segurança de tipo adicional - é possível atribuí-lo a uma variável inteira, o que está obviamente errado. Para código que não precisa suportar compiladores desatualizados, a melhor opção é nullptr. No contexto de ponteiro, a constante inteira zero significa "ponteiro nulo" - independentemente da representação binária real de um ponteiro nulo. Observe, no entanto, que se você deseja passar uma constante de ponteiro nulo para uma função em uma lista de variáveis como argumentos, você *deve* convertê-la explicitamente em um ponteiro - o compilador assume o contexto inteiro por padrão, o que pode ou não corresponder a representação binária de um ponteiro. <span id="Member_variables"></span> === Variáveis membro === Você encontrará quatro estilos principais de marcação de variáveis membro de classe no KDE, além de membros não marcados: * '''m_variable''' m minúsculo, sublinhado e o nome da variável começando com uma letra minúscula. Este é o estilo mais comum e o preferido para o código no kdelibs. * '''mVariable''' m minúsculo e o nome da variável iniciada com uma letra maiúscula * ''' variable_''' nome da variável começando com uma letra minúscula e, em seguida, um sublinhado * '''_variable''' sublinhado e o nome da variável começando com uma letra minúscula. Esse estilo geralmente é desaprovado, pois essa notação também é usada em algum código para parâmetros de função. Membros não marcados são mais comuns no caso de classes que usam [[Policies/Library Code Policy#D-Pointers|d-pointers]]. Como muitas vezes acontece, não há uma maneira correta de fazer; lembre-se de sempre seguir a sintaxe usada pelo aplicativo/biblioteca com a qual você está se comprometendo. Se você estiver criando um novo arquivo, siga o estilo de codificação da biblioteca ou módulo ao qual está adicionando o arquivo. Observe que os símbolos que começam com sublinhados são reservados para a biblioteca C (sublinhado seguido por Maiúscula ou sublinhado duplo são reservados ao compilador); portanto, se você puder, evite usar o último tipo. <span id="Static_variables"></span> === Variáveis estáticas === Tente limitar o número de variáveis estáticas usadas no seu código, especialmente ao comitar para uma biblioteca. A construção e a inicialização de um grande número de variáveis estáticas realmente prejudicam os tempos de inicialização. Não use variáveis estáticas de classe, especialmente em bibliotecas e módulos carregáveis, mesmo que isso seja desencorajado em aplicativos. Objetos estáticos levam a muitos problemas, como falhas difíceis de depurar devido a ordem indefinida de construção/destruição. Em vez disso, use um ponteiro estático, junto com <tt>K_GLOBAL_STATIC</tt>, definido em <tt>kglobal.h</tt> e usado da seguinte forma: <syntaxhighlight lang="cpp-qt"> class A { ... }; K_GLOBAL_STATIC(A, globalA) void doSomething() { A *a = globalA; ... } void doSomethingElse() { if (globalA.isDestroyed()) { return; } A *a = globalA; ... } void installPostRoutine() { qAddPostRoutine(globalA.destroy); } </syntaxhighlight> Consulte a [http://api.kde.org/4.x-api/kdelibs-apidocs/kdecore/html/group__KDEMacros.html#ga75ca0c60b03dc5e4f9427263bf4043c7 API documentation] para <tt>K_GLOBAL_STATIC</tt> para obter mais informações. <span id="Constant_data"></span> === Dados Constantes === Se você precisar de alguns dados constantes do tipo de dado simples em vários locais, faça melhor definindo-os uma vez em um local central, para evitar um erro de digitação em uma das instâncias. Se os dados mudarem, também há apenas um lugar que você precisa editar. Mesmo que exista apenas uma instância, você faz bem definindo-o em outro lugar, para evitar os chamados "números mágicos" no código que são inexplicáveis (cf. 42). Geralmente, isso é feito na parte superior de um arquivo para evitar procurá-lo. Defina os dados constantes usando os construtores da linguagem C ++, não as instruções do pré-processador, como você pode estar acostumado a partir do C puro. Dessa maneira, o compilador pode ajudá-lo a encontrar erros fazendo a verificação de tipo. <syntaxhighlight lang="cpp-qt"> // Correct! static const int AnswerToAllQuestions = 42; // Wrong! #define AnswerToAllQuestions 42 </syntaxhighlight> Se definir uma matriz constante, não use um ponteiro como tipo de dados. Em vez disso, use o tipo de dados e anexe à matriz o símbolo com comprimento indefinido, <tt> [] </tt>, atrás do nome. Caso contrário, você também define uma variável para alguns dados const. Essa variável pode ser atribuída por engano a um novo ponteiro, sem que o compilador se queixe. E ao acessar a matriz teria um engano, porque primeiro o valor da variável precisa ser lido. <syntaxhighlight lang="cpp-qt"> // Correct! static const char SomeString[] = "Example"; // Wrong! static const char* SomeString = "Example"; // Wrong! #define SomeString "Example" </syntaxhighlight> <span id="Forward_Declarations"></span> === Declarações Forward === Você reduzirá o tempo de compilação ao declarar classes forward quando possível, em vez de incluir seus respectivos cabeçalhos. As regras para quando um tipo pode ser usado sem ser definido são um pouco sutis, mas intuitivamente, se o único aspecto importante é o nome da classe, não os detalhes de sua implementação, uma declaração forward é permitida. São dois exemplos ao declarar ponteiros para a classe ou ao usar a classe como argumento de função. Por exemplo: <syntaxhighlight lang="cpp-qt"> #include <QWidget> // slow #include <QStringList> // slow #include <QString> // slow #include <QIcon> //slow class SomeClass { public: virtual void widgetAction( QWidget *widget ) =0; virtual void stringAction( const QString& str ) =0; virtual void stringListAction( const QStringList& strList ) =0; private: QIcon *icon; }; </syntaxhighlight> O trecho acima deve ser escrito assim: <syntaxhighlight lang="cpp-qt"> class QWidget; // fast class QStringList; // fast class QString; // fast class QIcon; // fast class SomeClass { public: virtual void widgetAction( QWidget *widget ) =0; virtual void stringAction( const QString& str ) =0; virtual void stringListAction( const QStringList& strList ) =0; private: QIcon *icon; }; </syntaxhighlight> <span id="Iterators"></span> === Iteração === <span id="Prefer_const_iterators_and_cache_end()"></span> ==== Preferir iteradores const e cache end() ==== Prefira usar <tt>const_iterators</tt> sobre iteradores normais, quando possível. Os contêineres que estão sendo compartilhados implicitamente geralmente são desconectados quando é feita uma chamada para um método non-const <tt>begin()</tt> ou <tt>end()</tt> ({{qt|QList}} um exemplo desse contêiner). Ao usar um const_iterator, observe também que você está realmente chamando a versão const de <tt>begin()</tt> e <tt>end()</tt>. A menos que seu contêiner seja realmente const, provavelmente não será esse o caso, possivelmente causando uma desconexão desnecessária do contêiner. Então, basicamente, sempre que você usa const_iterator, inicialize-os usando <tt>constBegin()</tt>/<tt> constEnd()</tt> em vez disso, para estar seguro. Coloque em cache o retorno da chamada do método <tt>end()</tt> (ou <tt>constEnd()</tt>) antes de fazer a iteração em contêineres grandes. Por exemplo: <syntaxhighlight lang="cpp-qt"> QList<SomeClass> container; //code which inserts a large number of elements to the container QList<SomeClass>::ConstIterator end = container.constEnd(); QList<SomeClass>::ConstIterator itr = container.constBegin(); for ( ; itr != end; ++itr ) { // use *itr (or itr.value()) here } </syntaxhighlight> Isso evita a criação desnecessária do objeto de retorno temporário <tt>end()</tt> (ou <tt>constEnd()</tt>) em cada iteração de loop, acelerando-a bastante. Ao usar iteradores, sempre use operadores de pré-incremento e pré-decremento (ou seja, <tt>++itr</tt>), a menos que você tenha um motivo específico para não fazê-lo. O uso de operadores pós-incremento e pós-decremento (isto é, <tt>itr++</tt>) causa a criação de um objeto temporário. <span id="Take_care_when_erasing_elements_inside_a_loop"></span> ==== Tenha cuidado ao apagar elementos dentro de um loop ==== Quando você deseja apagar alguns elementos da lista, você poderia talvez usar um código semelhante a este: <syntaxhighlight lang="cpp-qt"> QMap<int, Job *>::iterator it = m_activeTimers.begin(); QMap<int, Job *>::iterator itEnd = m_activeTimers.end(); for( ; it != itEnd ; ++it) { if(it.value() == job) { //A timer for this job has been found. Let's stop it. killTimer(it.key()); m_activeTimers.erase(it); } } </syntaxhighlight> Esse código vai potencialmente travar porque é um iterador pendente após a chamada para erase(). Você precisa reescrever o código desta maneira: <syntaxhighlight lang="cpp-qt"> QMap<int, Job *>::iterator it = m_activeTimers.begin(); while (it != m_activeTimers.end()) { if(it.value() == job) { //A timer for this job has been found. Let's stop it. killTimer(it.key()); it = m_activeTimers.erase(it); } else { ++it; } } </syntaxhighlight> Esse problema também é discutido na [https://doc.qt.io/qt-5/qmap-iterator.html#details Qt documentation for QMap::iterator], mas se aplica a '''todos''' iteradores Qt <span id="memory_leaks"></span> === vazamentos de memória === Um erro de programação muito "popular" é fazer um <tt>new</tt> sem um <tt>delete</tt> como neste programa: '''mem_gourmet.cpp''' <syntaxhighlight lang="cpp-qt"> class t { public: t() {} }; void pollute() { t* polluter = new t(); } int main() { while (true) pollute(); } </syntaxhighlight> Veja bem, ''pollute()'' instancia um novo objeto ''polluter'' da classe ''t''. Em seguida, a variável ''polluter'' é perdida porque é local, mas o conteúdo (o objeto) permanece no heap. Eu poderia usar este programa para tornar meu computador inutilizável em 10 segundos. Para resolver isso, existem as seguintes abordagens: * mantenha a variável na pilha em vez do heap: <syntaxhighlight lang="cpp-qt"> t* polluter = new t(); </syntaxhighlight> se tornaria <syntaxhighlight lang="cpp-qt"> t polluter; </syntaxhighlight> * exclua o polluter usando a função complementar para new: <syntaxhighlight lang="cpp-qt"> delete polluter; </syntaxhighlight> * interrompa o polluter em um [http://en.cppreference.com/w/cpp/memory/unique_ptr] (que excluirá automaticamente o polluter ao retornar do método) <syntaxhighlight lang="cpp-qt"> std::unique_ptr<t> polluter = new t(); </syntaxhighlight> Há também o std::shared_ptr e QSharedPointer. Essa é a maneira geralmente preferida de fazê-lo no C++ moderno; o gerenciamento explícito da memória deve ser evitado quando possível. O código Qt envolvendo QObject geralmente usa relações parent/child para liberar memória alocada; ao construir um QObject (por exemplo, um widget), ele pode receber um parent e, quando o parent é excluído, ele exclui todos os childs. O parent também é definido quando você adiciona um widget a um layout, por exemplo. Uma ferramenta para detectar vazamentos de memória como este é a [[Development/Tools/Valgrind|Valgrind]]. === dynamic_cast === Você só pode converter com dynamic_cast do tipo T de um tipo fornecido T2 que: * T é definido em uma biblioteca que você linka (você receberá um erro no linkador, se esse não for o caso, pois ele não encontrará as informações da vtable ou do RTTI) * T está "bem ancorado" nessa biblioteca. Por "bem ancorado", quero dizer que a vtable não é um símbolo COMUM sujeito a mesclagem em tempo de execução pelo linkador dinâmico. Em outras palavras, o primeiro membro virtual na definição de classe deve existir e não estar embutido: ele deve estar em um arquivo .cpp. * T e T2 são exportados Por exemplo, vimos alguns problemas difíceis de rastrear no código C++ que não é do KDE com o qual estamos linkando (acho que o NMM) por causa disso. Aconteceu que: * libphonon carrega o plugin NMM * Plugin NMM linka para o NMM * NMM carrega seus próprios plugins * Os próprios plugins do NMM linkam ao NMM Algumas classes na biblioteca do NMM não tinham vtables bem ancoradas; portanto, dynamic_casting falhou dentro do plug-in Phonon NMM para objetos criados nos próprios plug-ins do NMM. <span id="Program_Design"></span> == Design do Programa == Nesta seção, abordaremos alguns problemas comuns relacionados ao design de aplicativos Qt/KDE. <span id="Delayed_Initialization"></span> === Inicialização demorada === Embora o design dos aplicativos C ++ modernos possa ser muito complexo, as janelas do aplicativo podem ser carregadas e exibidas ao usuário muito rapidamente através da técnica de [http://www.kdedevelopers.org/node/509 delayed initialization]. Essa técnica é relativamente direta e útil em todas as etapas de um programa interativo. Primeiro, vejamos a maneira padrão de inicializar um aplicativo KDE: <syntaxhighlight lang="cpp-qt"> int main( int argc, char **argv ) { .... KApplication a; KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); MainWindow *window = new MainWindow( args ); a.setMainWidget( window ); window->show(); return a.exec(); } </syntaxhighlight> Observe que a <tt>janela</tt> é criada antes da chamada <tt>a.exec()</tt> que inicia o loop de eventos. Isso implica que queremos evitar fazer algo não trivial no construtor de nível superior, pois ele é executado antes que possamos mostrar a janela. A solução é simples: precisamos atrasar a construção de qualquer coisa além da GUI até depois que o loop de eventos for iniciado. Aqui está como o construtor da classe MainWindow de exemplo pode parecer para conseguir isso: <syntaxhighlight lang="cpp-qt"> MainWindow::MainWindow() { initGUI(); QTimer::singleShot( 0, this, SLOT(initObject()) ); } void MainWindow::initGUI() { /* Construct your widgets here. Note that the widgets you * construct here shouldn't require complex initialization * either, or you've defeated the purpose. * All you want to do is create your GUI objects and * QObject::connect * the appropriate signals to their slots. */ } void MainWindow::initObject() { /* This slot will be called as soon as the event loop starts. * Put everything else that needs to be done, including * restoring values, reading files, session restoring, etc here. * It will still take time, but at least your window will be * on the screen, making your app look active. */ } </syntaxhighlight> O uso dessa técnica pode não custar muito tempo para você, mas faz com que seu aplicativo pareça mais rápido para o usuário que o está iniciando. Esse aumento da capacidade de resposta percebida é reconfortante para o usuário, pois ele recebe um feedback rápido de que a ação de iniciar o aplicativo foi bem-sucedida. Quando (e somente quando) a inicialização não puder ser feita com rapidez suficiente, considere usar um {{class|KSplashScreen}}. <span id="Data_Structures"></span> == Estrutura de Dados == Nesta seção, abordaremos algumas das nossas queixas mais comuns que afetam as estruturas de dados comumente vistas nos aplicativos Qt/KDE. <span id="Passing_non-POD_types"></span> === Passando tipos non-POD === Tipos Non-POD ("plain old data") devem ser passados por const de referência sempre que possível. Isso inclui qualquer coisa além dos tipos básicos, como <tt>char</tt> e <tt>int</tt>. Tome, por exemplo, {{qt|QString}}. Eles sempre devem ser passados para os métodos como <tt>const {{qt|QString}}&</tt>. Embora o {{qt|QString}} seja compartilhado implicitamente, ainda é mais eficiente (e mais seguro) passar referências const, em oposição a objetos por valor. Portanto, a assinatura canônica de um método que usa argumentos QString é: <syntaxhighlight lang="cpp-qt"> void myMethod( const QString & foo, const QString & bar ); </syntaxhighlight> === QObject === If you ever need to delete a QObject derived class from within one of its own methods, do not ever delete it this way: <syntaxhighlight lang="cpp-qt"> delete this; </syntaxhighlight> This will sooner or later cause a crash because a method on that object might be invoked from the Qt event loop via slots/signals after you deleted it. Instead always use <tt>{{QtMethod|QObject|deleteLater}}</tt> which tries to do the same thing as <tt>delete this</tt> but in a safer way. === Empty QStrings === It is common to want to see if a {{qt|QString}} is empty. Here are three ways of doing it, the first two of which are correct: <syntaxhighlight lang="cpp-qt"> // Correct if ( mystring.isEmpty() ) { } // Correct if ( mystring == QString() ) { } // Wrong! "" if ( mystring == "" ) { } </syntaxhighlight> While there is a distinction between "null" {{qt|QString}}s and empty ones, this is a purely historical artifact and new code is discouraged from making use of it. === QString and reading files === If you are reading in a file, it is faster to convert it from the local encoding to Unicode ({{qt|QString}}) in one go, rather than line by line. This means that methods like <tt>{{qt|QIODevice}}::readAll()</tt> are often a good solution, followed by a single {{qt|QString}} instantiation. For larger files, consider reading a block of lines and then performing the conversion. That way you get the opportunity to update your GUI. This can be accomplished by reentering the event loop normally, along with using a timer to read in the blocks in the background, or by creating a local event loop. While one can also use <tt>qApp->processEvents()</tt>, it is discouraged as it easily leads to subtle yet often fatal problems. === Reading QString from a KProcess === {{class|KProcess}} emits the signals <tt>readyReadStandard{Output|Error}</tt> as data comes in. A common mistake is reading all available data in the connected slot and converting it to {{qt|QString}} right away: the data comes in arbitrarily segmented chunks, so multi-byte characters might be cut into pieces and thus invalidated. Several approaches to this problem exist: * Do you really need to process the data as it comes in? If not, just use <tt>readAllStandard{Output|Error}</tt> after the process has exited. Unlike in KDE3, KProcess is now able to accumulate the data for you. * Wrap the process into a {{qt|QTextStream}} and read line-wise. This should work starting with Qt 4.4. * Accumulate data chunks in the slots and process them each time a newline arrives or after some timeout passes. [https://cgit.kde.org/kdevelop.git/tree/kdevplatform/util/processlinemaker.cpp Example code] <span id="QString_and_QByteArray"></span> === QString e QByteArray === While {{qt|QString}} is the tool of choice for many string handling situations, there is one where it is particularly inefficient. If you are pushing about and working on data in {{qt|QByteArray}}s, take care not to pass it through methods which take {{qt|QString}} parameters; then make QByteArrays from them again. For example: <syntaxhighlight lang="cpp-qt"> QByteArray myData; QString myNewData = mangleData( myData ); QString mangleData( const QString& data ) { QByteArray str = data.toLatin1(); // mangle return QString(str); } </syntaxhighlight> The expensive thing happening here is the conversion to {{qt|QString}}, which does a conversion to Unicode internally. This is unnecessary because, the first thing the method does is convert it back using <tt>toLatin1()</tt>. So if you are sure that the Unicode conversion is not needed, try to avoid inadvertently using QString along the way. The above example should instead be written as: <syntaxhighlight lang="cpp-qt"> QByteArray myData; QByteArray myNewData = mangleData( myData ); QByteArray mangleData( const QByteArray& data ) </syntaxhighlight> === QDomElement === When parsing XML documents, one often needs to iterate over all the elements. You may be tempted to use the following code for that: <syntaxhighlight lang="cpp-qt"> for ( QDomElement e = baseElement.firstChild().toElement(); !e.isNull(); e = e.nextSibling().toElement() ) { ... } </syntaxhighlight> That is not correct though: the above loop will stop prematurely when it encounters a {{qt|QDomNode}} that is something other than an element such as a comment. The correct loop looks like: <syntaxhighlight lang="cpp-qt"> for ( QDomNode n = baseElement.firstChild(); !n.isNull(); n = n.nextSibling() ) { QDomElement e = n.toElement(); if ( e.isNull() ) { continue; } ... } </syntaxhighlight>
Toggle limited content width