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

  • prefix(prvé písmeno) E Napr.: EObject (E ako EMtest)
  • členské premené/membre objektu m Napr.: mPrivate
  • každé slovo názvu premennej začína veľkým písmenom Napr.: DataCollection
  • Ak je trieda v namespace-y, nepouzivat v cpp namespace-y pred triedou

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é

  • názvy lokálnych premenných začínajú malým písmenom Napr.: local
  • každé ďalšie slovo názvu premennej začína veľkým písmenom Napr.: dataCollectionWrite
  • a nezabúdať na to, že medzi lokálne premenné patria aj parametre funkcií!
  • nedopisovať na začiatok premenných zbytočné písmenká určujúce ich dátový typ ako napríklad bool bResult; unsigned long ulNumber; a pod. (tzv maďarská notácia)

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

  • názov typedef-u začína veľkým písmenom Napr.: typedef list<const EM::TicketIssueLogic::ETicketIssueLogicOutputData *> OutputDataList.
  • rovnako ako pri triedach a funkciách sa používa “CamelCase”.
  • preferuje sa typedef v ramci triedy.
  • v novsich (C++11) standardoch sa moze pouzivat namiesto typedef aj using.
  • using sa odporuca pouzit v co mozno najmensom adresnom priestore (v ramci tried a vo funkciach) a iba ked to pomoze citatelnosti kodu. Napriklad pri viacnasobne vnorenych sablonach s vacsim poctom parametrov, ktore sa v ramci funkcie pouzivaju na viacerych miestach (v konstrukcii: QList< QPair< const char*, const char* > > vnutorny Pair).

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

  • You have to deallocate with the operation that matches the allocation operation. When you allocate with new, you have to deallocate with delete. You have to match new[] with delete[]. You have to match malloc() with free(). And you have to match operator new with operator delete. Everything else is always undefined behaviour.
  • In other words: if using ::operator delete() on the void* works on your platform for PODs, delete or delete[] will probably work just as well. Doesn't change the fact that both are undefined behaviour.
  • The allocator objects used in the STL still follow this guideline. std::allocator uses ::operator new and ::operator delete to allocate and deallocate memory, then uses placement new and explicit destructor calls for construction and destruction.

Špeciality štruktúr

  • pri štruktúrach, ktoré idú do súboru, alebo sa prenášajú cez sieť … používať atribút packed v tvare:
__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));
  • Pozor na to, ze popisane riesenie je platformovo zavisle, vo windowse sa zarovnanie stuktur na 1 byte robi nasledovne:
#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;
  • Preto existuje v kniznici basedefs makro PACK, ktore umoznuje jeden zapis pre Win aj Lin.
  • atribut packed pouzivat len pri strukturach ku ktorym pristupujeme bajtovo

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

 
coding/rules_k10.txt · Last modified: 2018/03/09 12:14 by 192.168.242.36
 
Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki