C++
Introducere
Limbaj de programare
Ce este un limbaj de programare
"Un programator creaza/muta niste biti dintr-un loc in altul. Unealta cu care face acest lucru se numeste limbaj de programare."
Scopul unui limbaj de programare este de a exprima ideile sub forma unui cod pentru ca mai apoi masina de calcul sa le execute. Asadar, acesta trebuie sa fie cat mai "aproape" de masina de calcul.
Limbajul de programare C ofera exprimarea ideilor in cod intr-un mod clar si relativ simplu de inteles. "Extensia" limbajului C, adica C++, merge un pic mai departe si ofera programatorului de acest limbaj o solutie mai aproape de rezolvarea problemei.
"Sunt multe pareri in ceea ce priveste limbajele C si C++. Care ar trebui invatat mai intai ? Cele mai multe oferte de lucru dintre aceste doua limbaje sunt pe limbajul C++, insa nu poti intelege cu adevarat C++-ul si tot ce "ofera" acesta daca nu ai cunostinte si competente de macar nivel mediu asupra limbajului C."
Indiferent de limbajul de programare ales, acesta trebuie sa exprime ideile astfel:
- sa exprime ideile direct in cod intr-un mod cat mai simplu
- sa exprime o idee independenta independent de alte "idei" din cod
- sa ofere o "relatie" intre "ideile" din cod intr-un mod in care sa aiba sens
Tipuri de limbaj
Limbajele de programare sunt impartite in doua categorii, indiferent de mediul in care acestea ruleaza.
- limbaj interpretat
- limbaj compilat
Limbajele interpretate
Majoritatea limbajelor de programare si nu doar acestea sunt de acest fel. Aceste limbaje au nevoie de un interpretor pentru a "traduce" instructiunile scrise in acel limbaj (PHP, JavaScript, CSS, HTML etc.) in limbaj cod-masina. Unitatea de Procesare Centrala cunoaste doar acest limbaj cod masina. Acest interpretor este scris cel mai adesea in C si/sau C++.
Limbajele compilate
C/C++ este un limbaj compilat. Asadar, pentru a testa codul scris in acest limbaj, avem nevoie de un compilator. Pentru limbajul C se foloseste compilatorul gcc, abreviere de la GNU C Compiler. Pentru C++ se foloseste compilatorul g++. Ambele compilatoare reprezinta diferite programe ce contin cod masina si nu fac altceva decat sa "traduca" codul scris in limbaj masina. Mai exact, in mediul de lucru pe Linux, aceste "compilatoare" sunt de fapt niste legaturi (en. link-uri) catre adevaratele compilatoare ce compileaza programele noastre.
Stiluri de programare
- programarea procedurala
- programarea orientata pe obiecte
- abstractizarea datelor
- programarea generica
Majoritatea limbajelor de programare ofera suport pentru cel putin un astfel de stil de programare insa nu pentru toate aceste stiluri. Limbajul C++ ofera suport pentru toate aceste caracteristici.
Programarea procedurala
Programarea procedurala se bazeaza pe proceduri (functii apelate) executate cel mai adesea liniar, pas cu pas, de la primele linii de cod si pana undeva aproape de ultima linie de cod.
Toate limbajele de programare ofera suport pentru programarea procedurala. Pentru acest tip de programare a fost conceput limbajul C.
Programarea orientata pe obiecte
La baza programarii orientate pe obiecte stau clasele. Clasele reprezinta un sablon pentru obiectul/obiectele ce vor fi create in momentul instantierii acestui sablon.
Clasele pot fi mostenite. Acest lucru inseamna ca diferiti membri ai claselor pot fi declarati intr-o clasa si pot fi folositi in clasa sau clasele ce o mostenesc. Specificatorii de acces joaca un rol esential in acest sens.
Clasele ofera suport pentru polimorfism. Acest lucru inseamna ca o metoda (functie intr-o clasa) poate avea o versiune intr-o clasa si o alta intr-o clasa ce mosteneste.
Avantajele programarii orientate pe obiecte sunt urmatoarele:
- o mai clara structura a codului, fiind astfel mai usor de gestionat ori depanat probleme ce pot aparea - implementat mai usor diferite caracteristici noi
- scenariul de cod este executat mai rapid, ocupand mai putina memorie
- nu ne mai repetam in cod
- reduce complexitatea codului
- posibilitatea reutilizarii scenariului de cod cu obiecte in alte aplicatii
Abstractizarea datelor
Acest tip de programare se bazeaza pe diferite interfete/functii din diferite clase abstracte ce tin "ascuns" modul (codul sursa) cum realizeaza un rezultat. Abstractizarea datelor reprezinta o caracteristica a programarii orientate pe obiecte.
Programarea generica
Acest tip de programare se bazeaza pe diferite sabloane de clase generice ce pot lua "forma" obiectului atunci cand este instantiata clasa.
Istoric scurt al limbajului C++
Creatorul limbajul C++ este domnul Bjarne Stroustrup. Nascut in Danemarca, acesta a pus bazelele limbajului C++ in anul 1979. Initial, numele limbajului era C cu clase, insa din anul 1984 numele acestuia devine C++. La dezvoltarea limbajului C++ au contribuit multi programatori deveniti pasionati de acest limbaj. Trebuie recunoscut suportul oferit si de catre programatorii de la Bell Laboratories din compania AT&T. In cadrul acestui laborator Dennis Ritchie a creat limbajul C si este si cofondator al sistemului de operare UNIX.
In urmatoarea lista sunt prezentate cronologic evenimentele importante despre acest limbaj.
- 1979 - Domnul Bjarne Stroustrup pune bazele limbajului C cu clase avand ca inspiratie limbajele de programare Simula (considerat primul limbaj de programare cu suport pentru programarea orientata pe obiecte) si C. Inca de atunci (logic) au fost introduse clasele, constructorii si destructorul, specificatorii de acces private, protected si public dar si mostenirea intre clase.
- 1984 - "C cu clase" este redenumit in C++. Atunci sunt implementate caracteristici noi in limbaj, precum functiile virtuale, supraincarcarea operatorilor, referintele, libraria cu numere complexe si lucrul pe fluxul de intrare/iesire in terminal/fisier.
- 1985 - Mai exact in data de 14 Octombrie, C++ este prezentat oficial si poate fi folosit de catre programatorii din intreaga lume pentru uz comercial. Tot atunci este prezentata si prima carte despre limbaj, scrisa de autorul limbajului, The C++ Programming Language.
- 1989 - Domnul Bjarne Stroustrup publica cartea: The Annotated C++ Reference Manual
- 1991 - Domnul Bjarne Stroustrup publica versiunea a doua a cartii The C++ Programming Language. Tot atunci este inclus in limbaj programarea generica avand la baza clasele generice. Gestionarea erorilor prin clasa exception reprezinta o alta caracteristica adaugata in acel an.
- 1997 - Domnul Bjarne Stroustrup publica versiunea a treia a cartii The C++ Programming Language. Sunt incluse in limbaj ceea ce stim astazi ca fiind: libraria standard, namespaces, dynamic_cast, containere si algoritmi.
- 1998 - C++ are standard ISO
- 2003 - Sunt introduse in limbaj lucrul cu expresiile regulate si containerele neordonate.
- 2009 - Constructorul de "mutare", functia lamda, lucrul cu subprocese (en. thread-uri) reprezinta cateva caracteristici noi in limbaj ce au fost adaugate din acel an.
-
2011 - Apare versiunea C++11. Sunt introduse urmatoarele caracteristici:
- sunt introduse cuvintele cheie delete si default pentru a controla diferiti constructori si operatori de (concatenare) atribuire declarati in clase
- constructorul de "mutare"
- este introdus cuvantul cheie noexcept si (evident) functionalitatea acestuia
- este introdus in limbaj cuvantul cheie auto pentru a fi folosit la deducere automata
- posibilitatea de evaluare o expresie la compilare folosind noul cuvant constexpr
- functia lamda
- este introdus cuvantul cheie nullptr
- sintaxa noua de iterare cu structura repetitiva for - (en. base range for loop)
- posibilitatea de a suprascrie o functie folosind noul cuvant cheie override
- posibilitatea de a specifica daca o clasa sau o functie sa fie "ultima" - folosirea cuvantului cheie final
- operatorul "trei puncte" prin care putem specifica un numar nedefinit de argumente
- 2012 - C++11 devine oficial
- 2013 - Domnul Bjarne Stroustrup publica versiunea a patra a cartii The C++ Programming Language.
Invatand C++
"Inca exista o discutie legat de ce limbaj ar trebui sa inveti mai intai, C sau C++. Ideea generala este ca nu ai absolut nicio sansa sa intelegi pe deplin masina de calcul daca nu stii limbajul C. Daca vrei sa fi un bun programator pe C++, trebuie sa cunosti foarte bine si limbajul C. Daca vrei sa fi bun si pe limbajul C, trebuie sa intelegi programarea in sistemul de operare (en. system programming). C++ imprumuta si incorporeaza multe din caracteristicile limbajului C."
Nici-un limbaj de programare nu este perfect. Tocmai de aceea, "imperfectiunea" unui limbaj creaza spatiu pentru aparitia altuia mai bun. Acesta este si motivul aparitiei limbajului C++, o "extensie" a limbajului C.
Caracteristicile limbajului C++ fac din acesta o unealta mai potrivita in implementarea ideilor in cod comparativ cu limbajul C. Totodata, nu trebuie sa stirbim din ceea ce limbajul C poate sa faca. De exemplu, nucleul sistemului de operare Linux este scris aproape in totalitate in C si pe alocuri regasim cod scris in limbaj de asamblare. Asadar, nici vorba de C++.
Revenind la C++, acesta "furnizeaza" programatorului o sumedenie de clase generice predefinite si testate de-a lungul timpului ce pot fi incluse la nevoie in respectiva aplicatie. Aceste clase ofera o mai buna gestionare a resurselor calculatorului printr-o mai buna gestionare a memoriei, o comunicare mai buna intre procese (un proces este un program in executie), o gestionare mai buna al erorilor in cod, fie ca este la compilarea programului ori la executarea programului rezultat. Aceste caracteristici reprezinta doar o mica parte din ceea ce C++ ofera prin intermediul claselor generice. Programarea generica reprezinta punctul forte al C++-ului iar clasele din libraria standard sunt scrise astfel.
Cuvinte rezervate in limbaj
Fiecare limbaj de programare contine o lista intreaga de cuvinte ce au un scop precis in acel limbaj si nu pot fi folosite decat in acel scop. Pe multe dintre acestea le putem intalni si in alte limbaje de programare, insa o parte sunt specifice limbajului respectiv. Mai mult decat atat, nici-un limbaj de programare nu este "static", acesta este imbunatatit cu fiecare noua versiune, asadar putem avea cuvinte rezervate noi. C++ nu face exceptie. Lista urmatoare prezinta cuvintele rezervate in C++.
-
C++
- and
- and_eq
- asm
- atomic_cancel
- atomic_commit
- atomic_noexcept
- bitand
- bitor
- bool
- break
- case
- catch
- char
- class
- compl
- const
- const_cast
- continue
- do
- double
- dynamic_cast
- else
- enum
- explicit
- export
- extern
- false
- float
- for
- friend
- goto
- if
- inline
- int
- long
- mutable
- namespace
- new
- not
- not_eq
- operator
- or
- or_eq
- private
- protected
- public
- reflexpr
- register
- reinterpret_cast
- return
- short
- signed
- sizeof
- static
- static_cast
- struct
- switch
- synchronized
- template
- this
- throw
- true
- try
- typedef
- typeid
- typename
- union
- unsigned
- using
- virtual
- void
- volatile
- wchar_t
- while
- xor
- xor_eq
-
C++ 11
- alignas
- alignof
- auto
- char16_t
- char32_t
- constexpr
- default
- delete
- decltype
- final
- override
- noexcept
- nullptr
- static_assert
- thread_local
-
C++ 20
- char8_t
- concept
- consteval
- constinit
- co_await
- co_return
- co_yield
- import
- module
- requires
Cele mai folosite cuvinte cheie folosite in Programarea Orientata pe Obiecte in C++
Programarea cu clase in C++ reprezinta primul pas in invatarea acestui limbaj. Presupun ca limbajul C iti este cunoscut. Clasele sunt la baza programarii orientate pe obiecte. C++ are o multime de cuvinte rezervate in limbaj ce au un rol specific in lucrul cu clasele. Desi putem folosi aproape toate cuvintele rezervate in limbaj in interiorul unei clase, de cele mai multe ori vom folosi cuvintele din urmatoarea lista:
- class
- template
- typename
- new
- delete
- operator
- this
- private
- protected
- public
- friend
- return
- virtual
- default
- inline
- static
- explicit
Scurta descriere despre libraria standard din C++
O buna parte din timpul alocat invatarii limbajului C++ este atribuit invatarii librariei standard. Aceasta contine multe fisiere. O parte din acestea sunt prezentate in lista de mai jos si sunt rezumate la urmatoarele activitati:
-
flux de intrare/iesire (terminal/fisier)
-
terminal
-
intrare
- cin
-
iesire
- cout
- cerr
- clog
-
intrare
-
fisier
-
intrare
- clasa ofstream
-
iesire
- clasa ifstream
-
intrare si iesire
- clasa fstream
-
intrare
-
terminal
-
containere ce vor contine date
-
containere secventiale
- array
- vector
- list
- forward_list
- deque
-
containere adaptori
- stack
- queque
- priority_queue
-
containere asociative ordonate
- set
- map
- multiset
- multimap
-
containere asociative neordonate
- unordered_set
- unordered_map
- unordered_multiset
- unordered_multimap
-
containere secventiale
-
gestionarea memoriei prin pointeri inteligenti (elibereaza automat memoria) (en. smart pointers)
-
fisierul memory
- unique_ptr
- shared_ptr
- weak_ptr
-
fisierul memory
-
gestionarea mai multor subprocese (en. multithreading)
- fisierul thread
- libraria POSIX pthread.h - folosit cel mai adesea in C, nu este parte din C/C++ (la acest moment) si necesita compilare cu optiunea -pthread in gcc / g++
Fisierele din C in C++
C++ include in libraria standard aproape toate fisierele din C insa cu o denumire aproape identica. In C++, acestor fisiere li se inlatura extensia iar la denumirea lor li se adauga litera c. In tabelul urmator puteti vedea cateva exemple.
| C | C++ |
|---|---|
| stdio.h | cstdio |
| signal.h | csignal |
| stdlib.h | cstdlib |
| string.h | cstring |
| time.h | ctime |
| limits.h | climits |
Editoare de text
Fiecare programator este liber sa foloseasca orice editor de text ce ii face munca mai usoara. In exemplele de mai tarziu ma voi folosi de editorul SublimeText sau nano doar pentru a scrie codul. Pentru compilarea programului voi folosi compilatorul g++ din linia de comanda. Sistemul de operare pe care il folosesc este Linux. De cele mai multe ori compilatoarele gcc si g++ nu vin instalate pe Linux si trebuie instalate manual din linia de comanda.
"Folosirea acestor unelte este o decizie personala pentru ca vreau sa fiu mai aproape de sistemul de operare. De foarte multe ori folosesc doar nano si gcc/g++ pentru ca inca vreau sa fiu capabil sa lucrez si pe sisteme de operare de tip text, adica fara interfata grafica."
Alte editoare de text mai sunt CodeBlocks sau Visual Studio. Acesta din urma este si cel mai popular. Ambele "contin" compilatoarele gcc si g++ si poti testa direct codul scris.
Recomandari despre C/C++
Mai multe recomandari trebuie retinute inainte de a incepe sa scrii prima linie de cod in C/C++. In urmatoarele subcategorii sunt prezentate cateva dintre aceste recomandari. Daca ai ceva experienta cu aceste limbaje, pe unele sau chiar pe toate le vei recunoaste, in caz contrar este bine sa le reti pentru mai tarziu.
Recomandari pentru programatorii de C++
- incearca sa eviti pe cat posibil folosirea operatorilor impliciti in limbaj de alocare/dealocare memorie, adica new si delete - foloseste in schimb pointeri inteligenti care aloca si elibereaza memoria automat
- foloseste perechea constructor/destructor pentru a simplifica gestionarea memoriei alocate dinamic cu new si dealocate cu delete
- foloseste clasele container in detrimetrul tipurilor de date rudimentare din limbaj (vectorilor/matricelor (en. array-uri)) atunci cand vrei sa salvezi date complexe
- foloseste iteratorii prezenti implicit in containere in detrimetrul celor generali
- gestioneaza erorile/exceptiile aparute intotdeauna cu clasa exception
- foloseste din plin ceea ce C++ iti ofera si evita pe cat posibil sa scrii cod din limbajul C in C++
Recomandari si ponturi pentru programatorii de C ce vor sa scrie cod C++
- nu folosi tipul de data char decat daca nu ai incotro, foloseste "tipul de data" string
- nu folosi tipul de data tablou/matrice (en. array), foloseste containerul vector (sau altul mai adecvat cerintelor si cu cea mai buna performanta)
- nu incerca sa concatenezi un sir de caractere char la altul in C++ folosind functia din C strcpy(), foloseste "tipul de data" string ce iti permite sa faci acest lucru mai rapid si elegant (are supraincarcat operatorii + si +=)
- nu folosi niciodata functiile de alocare, realocare si dealocare a memoriei din C (malloc(), realloc() si free()) in C++ - foloseste operatorii new sau delete sau mai bine pointeri inteligenti unique_ptr si/sau shared_ptr
- nu incerca sa convertesti un tip de data la un altul asa cu se face in C, foloseste ceea ce C++ iti ofera, adica clasele static_cast pentru conversie la compilarea programului si dynamic_cast pentru conversie la executia programului - folosirea conversiei de la un tip de data la altul, fie ca este in C sau C++ reprezinta un defect de proiectare
- daca folosesti programarea cu subprocese (en. multithreading) din C (libraria POSIX pthread.h) in C++, nu uita ca la compilare in linia de comanda sa folosesti si optiunea -pthread
- nu presupune ca tot ceea ce este scris in C este obligatoriu compilat mai rapid si programul rezultat este mai rapid decat in C++ - compilatorul de C++ nu "traduce" codul din C++ in C si apoi in limbaj de asamblare si apoi in cod masina, ci cel mai probabil va "sari" peste traducerea in C si poate si peste cea in limbaj de asamblare
- atunci cand direct sau indirect apelezi functii in sistem (en. system calls) (in C sau C++) pentru a aloca memorie (new, metoda push_back din vector etc.), scrie intr-un fisier etc., sistemul de operare schimba statusul programului tau din TASK_RUNNING in TASK_INTERRUPTIBLE, facandu-l sa nu mai ruleze, il pune intr-o lista de asteptare (o coada ce contine si alte procese) pana ce acel apel in sistem si-a terminat treaba si a returnat o valoare intr-unul din registrii Unitatii de Procesare Centrale, apoi sistemul de operare schimba din nou statusul programului in TASK_RUNNING si executa codul de "unde" a ramas
- retine ca memoria dealocata din C sau C++ nu se "reintoarce" imediat la sistemul de operare, acesta din urma o rezerva tot pentru procesul respectiv pentru a-i fi "servita" din nou la cerere
Anatomia unui program
Functia main
Fiecare program existent are un inceput al tuturor instructiunilor. Acesta este reprezentat de catre functia main. Aceasta functie este executata automat de catre sistemul de operare atunci cand programul cu pricina este executat, devenind proces. Functia main reprezinta functia "radacina" si va putea apela (daca este scris codul in asa maniera) alte functii care la randul lor vor apela alte functii s.a.m.d. Nu este obligatoriu ca functia main sa apeleze si alte functii asa cum nu exista o limita in ceea ce priveste numarul de functii apelate in functia main.
Sintaxa pentru declararea unei functii
Orice functie declarata in C sau C++ este compusa in cea mai mare parte din:
-
tipul de date returnat de functie (sunt prezentate doar o parte)
- void - inseamna ca nu returneaza nimic
- void * - returneaza un pointer de tip void
- int / long int / long long int - returneaza un tip de data numeric intreg
- float - returneaza un tip de data cu fractie (o singura cifra dupa virgula)
- double - returneaza un tip de data cu fractie (doua cifre dupa virgula)
- struct nume-structura - returneaza o structura
- struct *nume-structura - returneaza un pointer la o structura
- numele functiei
- o pereche de paranteze ce va contine zero sau mai multi parametri formali - daca nu contine nimic, putem adauga cuvantul cheie void
- o pereche de acolade ce va reprezenta "corpul" functiei si va contine codul propriu-zis
IMPORTANT: Daca o functie returneaza un tip de data intreg, de obicei un "int", acest lucru poate insemna ca orice valoare diferita de cifra zero inseamna un tip de eroare. Cifra zero inseamna ca functia respectiva a executat codul cu "succes" si nu au fost erori.
Comenzile preprocesor
In momentul cand un program este compilat, compilatorul verifica daca exista in codul scris din programul respectiv una sau mai multe comenzi preprocesor. Mai toate programele au nevoie de cel putin o comanda preprocesor pentru ca este aproape imposibil ca un program sa nu aiba nevoie de diferite resurse (citirea/scrierea intr-un fisier, comunicarea cu un alt (sub)proces sau proces copil etc.) ale masinei de calcul oferite de sistemul de operare prin includerea de fisiere ce ofera aceasta facilitate.
O comanda preprocesor este "identificata" prin faptul ca la un inceput de rand avem un caracter diez urmat imediat de un cuvant format doar din litere. Obligatoriu, dupa acest cuvant urmeaza un caracter spatiu si apoi restul de comanda preprocesor.
Cea mai folosita comanda preprocesor este #include. In lista urmatoare se poate observa toate aceste comenzi preprocesor.
- #define
- #elif
- #else
- #endif
- #error
- #if
- #ifdef
- #ifndef
- #import
- #include
- #line
- #pragma
- #undef
- #using
Comanda preprocesor #include
Indiferent ca scrii codul in C sau C++ vei folosi aceasta comanda pentru a spune preprocesorului (program executat inainte de compilarea intregului program) sa includa continutul unui fisier in locul comenzii preprocesor. Acest fisier poate fi reprezentat intre doua paranteze unghiulare sau intre doua ghilimele. In cazul in care se folosesc parantezele unghiulare, preprocesorul "stie" unde se afla acel fisier in sistemul de operare. Stie pentru ca la instalarea editorului de text (CodeBlocks / Visual Studio) sau a compilatorului, acele fisiere sunt adaugate intr-un director specific (pe Linux le vei gasi in directorul /usr/include). In situatia in care la includerea continutului unui fisier sunt folosite ghilimele, va trebui sa specifici calea relativa din acel fisier pana la fisierul ce trebuie inclus.
De cele mai multe ori vei folosi parantezele unghiulare pentru a include continutul unui fisier ce iti ofera "acces" la diferite functii (in C) sau clase (in C++) prin care te folosesti de facilitatile oferite de acestea. Ghilimele le vei folosi pentru a include continutul unui fisier ce ar contine declararea unei functii globale sau al unor metode dintr-o clasa. Ai putea sa folosesti ghilimele pentru a include continutul unui fisier ce contine exclusiv alte "include-uri" cu paranteze unghiulare.
Cuvantul rezervat namespace si libraria standard
Indiferent ca scrii cod in limbajul C sau C++, vei avea nevoie de resursele oferite de sistemul de operare. Limbajele C si C++ nu au caracteristici incluse pentru a accesa resursele calculatorului. Din acest motiv, programatorii de aceste limbaje folosesc cel putin o librarie pentru a accesa resursele calculatorului.
Libraria cea mai folosita in C este Libraria Standard. In C "gasim" o multime de librarii ce vin instalate odata cu compilatorul gcc. Aceste librarii sunt incluse in cea mai mare parte si in cadrul Librariei Standard din C++. Trebuie tinut cont ca in C++, Libraria Standard este organizata intr-un "container" namespace cu denumirea de std, abreviere de la Standard Template Library. In cadrul acestui namespace vom putea vedea o multime de clase cu rol specific ce alcatuiesc aceasta librarie.
IMPORTANT: Putem include intr-un namespace oricate namespace-uri ne dorim, insa acest lucru nu este recomandat. Rolul unui namespace este sa formeze o librarie ce va contine clase si/sau diferite functii.
Cuvantul rezervat using
Cuvantul rezervat using reprezinta posibilitatea ca un membru sau chiar toti dintr-un namespace sa devina global in scopul/mediul respectiv. Cel mai adesea cuvantul using este folosit impreuna cu cuvantul namespace. Rezultatul fiind ca toti membri respectivului namespace (va trebui sa specificam si numele acestuia dupa namespace) sa fie accesibili in acel scop.
Primul program in C++
Nume de fisiere
Programele pe care le vom scrie vor fi (evident) in fisiere de tip text ce codeaza caracterele dupa codul ASCII. Aceste fisiere pot avea orice nume ne dorim, insa este recomandat sa se tina cont de semantica in alegerea numelui fisierului iar extensia fisierului sa fie .h pentru "header-uri" - fisiere ce vor contine prototipurile/definitiile functiilor/claselor si .cpp pentru fisierele ce vor contine declaratiile functiilor/claselor.
Primul program
Este timpul sa punem totul impreuna. Vom include cu #include fisierul iostream (flux de intrare/iesire in linia de comanda) din Libraria Standard, apoi, pe urmatoarea linie de cod vom folosi cuvintele cheie using si namespace pentru a "aduce" in acest scop toti membri acestui fisier ce apartin librariei standard. Dupa aceste linii de cod vom declara functia main in care vom folosi obiectul cout urmat de operatorul << si apoi de textul ce va fi afisat in linia de comanda.
#include <iostream>
using namespace std;
int main(){
cout << "Salutare din C++!\n";
}
OBSERVATIE: Aproape dupa fiecare linie de cod se adauga intr-un singur exemplar caracterul punct si virgula. Acesta are ca rol sa ii "spuna" compilatorului ca in acel loc se termina respectiva instructiune.
Compilarea unui program
Limbajele C si C++ sunt limbaje compilate. "Traducerea" codului scris in caracterele scrise de la tastatura in limbaj binar presupune folosirea in C si C++ a unui compilator. Pentru C se foloseste compilatorul gcc. In cazul C++-ului se foloseste g++.
Compilarea folosind IDE-uri
Daca folosesti un IDE, cum este cazul programelor CodeBlocks sau Visual Studio, compilarea se va face folosind interfata grafica al acestor programe. Nu voi explica cum acest lucru se face, va trebui sa va descurcati singuri, este foarte usor.
Compilarea din linia de comanda pe Linux
Instalarea compilatoarelor gcc si g++
De obicei, programatorii stiu sa lucreze si in linia de comanda indiferent de sistemul de operare. Daca lucrezi pe Linux, trebuie sa te asiguri ca ai instalat pe distributia ta de Linux aceste compilatoare. Pentru a instala aceste compilatoare trebuie sa stii ca pentru fiecare distributie Linux exista un program special pe care il folosesti la instalarea acestor compilatoare dar si al altor programe. Ne vom rezuma doar la instalarea acestor compilatoare pentru fiecare distributie in parte. Pentru a instala un program vei avea nevoie sa rulezi programul de instalare (apt/yum/pacman) cu drepturi de administrator (va trebui sa introduci si parola de administrator), de aceea se afla comanda sudo (substituite user do) prezenta. Nu uita ca dupa ce ai scris comanda in linia de comanda, sa apesi tasta Enter.
-
Debian - o parte din sistemele de operare Linux
- Ubuntu
- Kali
- Mint
- Raspbian
- Comenzi folosite:
- sudo apt install gcc -y
- sudo apt install g++ -y
-
Fedora
- Fedora
- Comenzi folosite:
- sudo yum install gcc -y
- sudo yum install g++ -y
-
Arch
- Manjaro
- Comenzi folosite:
- sudo pacman -S gcc
- sudo pacman -S g++
Compilarea programului din linia de comanda pe Linux
Este recomandat sa cititi si documentatia specifica a compilatorului. Aceasta se poate vedea din linia de comanda folosind comanda man (manual) urmat de numele compilatorului.
man gcc
man g++
Pentru a te reintoarce inapoi in "ecranul" anterior executarii comenzi, apasa tasta Q (Quit).
Nume si extensie implicita al programelor executabile
Pe Linux, fisierul ce este compilat fara a i se specifica un nume si o extensie pentru fisierul executabil rezultat, compilatorul il va denumi a.out. De exemplu, un fisier text cu denumirea de test si extensia .c sau .cpp va putea fi compilat in C si C++ astfel:
gcc test.c
g++ test.cpp
Compilarea programelor cu rezultarea unui nume de fisier dat de noi
Acest lucru se va putea realiza folosind optiunea -o (en. output) data compilatorului.
gcc test.c -o test
g++ test.cpp -o test
In ambele exemple de mai sus, rezultatul va fi un fisier executabil cu numele de test si fara extensie. Trebuie sa fiti atenti sa nu mai existe un astfel de fisier in acel director, altfel il veti suprascrie.
Pasii facuti de compilator in compilarea fisierelor sursa
| nume-fisier1.cpp | nume-fisier2.cpp |
|---|---|
| ↓ | ↓ |
| compilare nume-fisier1.cpp | compilare nume-fisier2.cpp |
| ↓ | ↓ |
| rezultat nume-fisier-obiect1 | rezultat nume-fisier-obiect2 |
| ↓ | |
| program de legatura ce va face legatura intre fisierele obiect | |
| ↓ | |
| fisier executabil | |
IMPORTANT: Fisierul executabil rezultat este compatibil pentru respectiva arhitectura hardware si pentru acea gama de sisteme de operare. Daca ai compilat programul tau pe Linux, acesta va putea fi executat doar pe Linux. Daca vrei sa ruleze si pe Windows, va trebui sa il compilezi din nou si pe Windows. Codul sursa al fisierelor este portabil, nu si fisierul executabil rezultat. Implicit, pe Linux, extensia fisierelor executabile este .out si este optionala. Pe Windows este .exe. Continutul fisierelor executabile pe Linux si Windows este diferit, desi au acelasi cod sursa.
Executarea programului
In directorul unde a fost creat fisierul executabil, deschideti linia de comanda in acel director sau navigati din linia de comanda pana in acel director si "apelati" fisierul executabil in linia de comanda specificandu-i numele precedat de caracterele ./ (punct si slash). Acestea sunt necesare pentru a spune programului SHELL din Linux sa execute fisierul tau din directorul curent, altfel SHELL va "crede" ca respectivul fisier se afla in directorul /bin si va incerca sa il execute de acolo. Asadar, daca programul rezultat are numele de test, il vom putea apela astfel.
./test
Aceasta informatie devine utila mai tarziu, cand vom si scrie si compila codul scris in C/C++.
Anatomia unui proces
Un program in executie se numeste proces. Atunci cand executam/apelam un fisier executabil, sistemul de operare ii face o copie de pe hardisk in memoria RAM, apoi ii atribuie mai multe "resurse" iar cateva sunt prezentate in lista urmatoare.
- un spatiu de memorie alocat in memoria RAM - niciodata acelasi fata de executia anterioara a programului
- memorie stiva suplimentara
- memorie heap suplimentara
-
legatura catre trei fisiere temporare ce vor fi sterse la terminarea executarii procesului
- in C stdin, stdout, stderr
- in C++ cin, cout, cerr, clog - ultimul este identic cu cerr
- un numar de identificare unic, denumit Process ID
- diferite "drepturi de acces", asa zisele credentiale