Table of Contents

Triedy a struktury

Nazvy tried a struktur

Názvy sa tvoria výhradne z anglických slov. Ohladom nazvov pozri: Nazvoslovia

Pimpl

Pre triedy rozhrani obsahujuce membre sa pouziva pimpl princip: Pimpl

Triedy

Privátne triedy

Kvôli čistote kódu a v prípade knižníc zabezpečovaniu binárnej kompatibility pri pridávaní členských premenných do tried je potrebné celú privátnu časť triedy zapuzdrovať do osobitnej triedy nasledovným spôsobom:

(viac o binarnej kompatibilite tu: Binarna_kompatibilita. Viac o tomto principe tu: Pimpl_Idiom)

class Class
{
public:
     Class();
     ~Class();

     //TODO all public members

private:
     class DataClass;
     DataClass* d;
};

Táto trieda je v hlavičkom súbore iba dopredne deklarovaná, definícia triedy sa nachádza v prislušnom cpp (najlepšie na začiatku)

class Class::DataClass
{
public:
      //TODO all private members and methods
};

Privátny member d bude alokovaný v konštruktore a dealokovaný v deštruktore Class

Treba si uvedomiť, že na takúto triedu defaultny copy konštruktor už postačovať nebude, preto ho treba implementovať napríklad takto:

Class::Class( const Class& rhs )
{
     d = new Class::DataClass( *rhs.d );
}

V pripade, ze je potrebne mat pristup k majitelovi datovej triedy, je vhodne zvazit ci je naozaj potrebne tento pristup mat (moze to smerovat k zlemu dizajnu) ak ano, tak by sa premenna mala volat mDataClassOwner. Tento smernik nie je mozne poskytovat mimo triedy Class.

class Class::DataClass
{
public:
        Class *mDataClassOwner;
        //other private members and methods
};

Qt5 a shared pointre

Pre projekty v standarde c++11 a Qt5 (Vesna) sa pouziva mechanizmus QSharedPointer a osobitne pre datove tiredy mechanizmus QScopedPointer. Tym sa zabezpeci automaticke mazanie datovej triedy v destruktore predka. Potom priklad vyzera nasledovne:


#include <QScopedPointer>

class Class
{
public:
     Class();
     ~Class();

     //TODO all public members

private:
     class DataClass;
     QScopedPointer<DataClass> d;
};
Class::Class( )
{
     d.reset( new DataClass() );
     // pri shared pointroch je mozny zapis:
     // d = QSharedPointer<Class::DataClass>( new Class::DataClass() );
     // ale pre vacsiu prehladnost pouzivame metodu reset().
}

Class::~Class()
{
     // do not delete DataClass
}

Lokálne premenné

Enum

  1. názov enum-u začína veľkým písmenom Napr.: enum Fonts
  2. rovnako ako pri triedach a funkciách sa používa “CamelCase”, napr. enum TextHorizontalAlignmet
  3. pre jednotlivé položky enum-u sa používa rovnaká notácia ako pre názov. Pre jednoznačnejšie názvy môžeme na začiatok názvu položky dať prefix hovoriaci do ktorého enum-u položka patrí. Napr:
enum IssueState
{
     StateDefault,
     StateSelected,
     StateConfirmed
}

Typedef / using

Include-y

  1. include-y píšeme s rozsirenou relativnou cestou (od zaciatku projektu) cestou kvôli prehľadnosti .pro-súboru, kompilácia ide o trošku rýchlejšie a hlavne ak sú dva súbory s rovnakým názvom je nad slnko jasnejšie, ktorý z nich bude includnutý<br>
    #include "EXML/EXMLAttrib.h"
    
  2. do hlavičkových súborov pridávať LEN nutné include-y a ako prvé systémové include-y. To znamená použiť include len v prípade, že dopredná deklarácia nefunguje. Vo všeobecnosti platí, že musí byť include na:
    1. triedu, po ktorej aktuálna trieda dedí
    2. triedu, ktorej inštancia je nedynamickým membrom aktuálnej triedy
    3. stl string, stl vector (a myslim ze aj na stl mapu a list). V podstate všetky typedef-y<br>
            #ifndef _a_h_included_
            #define _a_h_included_
            #include <string>
            #include <vector>
            #include "abase.h"
            #include "b.h"
      
            // Forward Declarations
            class C;
            class D;
      
            class A : public ABase
            {
            public:
                void SetC(vector<int> *c);
                C *GetC() const;
        
              void ModifyD(D *d);
      
            private:
                std::string mName;
                B mB;
                C *mC;
                D *mD;
            };
            #endif
            
  3. v cpp odporúčam logicky separovať include-y do skupín (každú skupinu popísať commentom) s tým, že ako prvý má byť include na hlavičkový súbor, ktorý prislúcha danému cpp, potom na systémové .h súbory, potom na Qt, potom zvyšné a nakoniec na logy (emlog). Za include-y môžme napísať v cpp using namespace na potrebné nasmpace-y. Za porušenie strieľať nebudeme, ale je to takto prehľadnejšie.<br>
        /// HEADER INCLUDE
        #include "EUI.h"
    
        /// SYSTEM INCLUDES
        #include <algorithm>
    
        /// QT INCLUDES
        #include <qobject.h>
    
        /// BASE INCLUDES
        #include "EUIDefines.h"
        #include "EUIDriver.h"
        #include "EUIDriverCreator.h"
        #include "EUIImplementationDirectFB.h"
        #include "EObject.h"
    
        /// COMMANDS INCLUDE
        #include "ECmdSetText.h"
        #include "ECmdWindowOperation.h"
        #include "ECmdAddWindow.h"
    
        /// XML INCLUDES
        #include "EXML/EXMLAttrib.h"
    
        /// DEVICESYSTEM INCLUDES
        #include "edevicesystem/EDriverProperties.h"
    
        /// LOGS
        #define __USE_LOG__
        #include "emlog.h"
        DECLARE_LOG_OBJECT();
    
        /// NAMESPACES
        using namespace EM::Devices;
        using namespace std;
        

Alokovanie a dealokovanie

Pouzitie new / malloc vs. delete / free

Špeciality štruktúr

__attribute__ ((packed));

32 bitovy procesor vyhradzuje 4 byte pre kazdy typ premenej nezavisle od typu (char, short, long)

struct EMSKUsedTTZonesHeader
{
	unsigned char version;		//pozicia 0, dlzka 2
	unsigned short headerSize;	//pozicia 2, dlzka 2	
	unsigned long line;	//pozicia 4, dlzk 4
	unsigned long trip;	//pozicia 8, dlzka 4
	unsigned short recordSize;
} __attribute__ ((packed));
#pragma pack( push, 1 )
typedef struct _BMP_header
{
unsigned short ImageFileType;
unsigned long FileSize;
unsigned short Reserved1;
unsigned short Reserved2;
unsigned long ImageDataOffset;
} 
#pragma pack(pop)
BMP_header;

problemy s packet:

ak je struktura napr.
Struct A
{
long a;
char b;
long c;
};
a mame funkciu 
void funkcia(long *x)
{
	*x = 5;
}
a pouzitie...
A xy;
funkcia(&xy.c);
pri plneni premenej x (*x=5) je pointer na premenu x posahany

Const

Pravidla pouzivania a vysvetlenie pouzivania: Const pouzivanie a vysvetlenie