Limbajul C++ si oop abc-doar


celor doua biblioteci,editati o aplicatie de genul



Yüklə 1,36 Mb.
səhifə9/18
tarix12.09.2018
ölçüsü1,36 Mb.
#81721
1   ...   5   6   7   8   9   10   11   12   ...   18

celor doua biblioteci,editati o aplicatie de genul:

#include

#include

#include

main()

{

cout << "Maximum dintre 12 si 7 este: "<

cout << "Minimum dintre 12 si 7 este: "<

getch();

return 0;

}


-54-

O alta metoda destul de practica este cea prin care biblioteca statica

realizeaza atat exportul cat si importul datelor din fila DLL.Pentru

acest scop,in fila DLL se declara o variabila oarecare cu ajutorul careia

biblioteca statica va putea face distinctia dintre fila DLL si fila

aplicatie.Daca variabila este definita,biblioteca va exporta datele iar

daca variabila nu este definita biblioteca va importa datele:

EXEMPLU: (vezi si directorul DLLTest3)

In acest caz,primul pas este reprezentat de editarea filei header:

//Test3.h

#ifdef MODULDLL

#define IMPEXP __declspec(dllexport)

#else

#pragma comment(lib,"DLL3.LIB")

#define IMPEXP __declspec(dllimport)

#endif

IMPEXP int fnTest(int a);

Salvati fila cu numele Test3.h in directorul INCLUDE.

In rest se procedeaza identic,dar fila dll3.cpp va arata astfel:

#define MODULDLL

#include

IMPEXP int fnTest(int a){ a=a+33; return a;};

int WEP(int b)

{

b=1;

return b;

};

Iar fila .cpp din aplicatia test3.cpp va arata astfel:

#include

#include

#include

main()

{

cout << "text \n";

int b;

b=fnTest(15);

cout << "Functia fnTest() returneaza: " << b;

getch();

return 0;

}

Observati ca in loc de "_export" s-a utilizat: "__declspec(dllexport)" iar

in loc de "_import" s-a utilizat: "__declspec(dllimport)".

Pentru versiunile noi,cele doua cuvinte cheie au fost inlocuite prin

formulele de mai sus,care asigura o mai buna compatibilitate cu formatul

de 32 de biti.Pentru toate DLL-urile Windows si pentru cele nou create

se recomanda utilizarea acestor formule.Cuvintele cheie vor fi rezervate

doar pentru compatibilitatea cu programele mai vechi.

Asadar,cele doua tipuri de biblioteci pot fi combinate cu succes pentru

a beneficia de avantajele oferite de fiecare tip in parte.

Exemplele de mai sus,ofera doar o imagine simplista a modului in care

se pot crea sau apela diversele tipuri de biblioteci.Solutia optima de-

pinde de necesitatile programului si de experienta programatorului.


-55-

Adevaratele probleme apar atunci cand se utilizeaza mai mult decat o

singura biblioteca DLL.Fiecare biblioteca DLL,in momentul in care este

"linkata" la o aplicatie,creaza un fel de "spatiu virtual" in care toate

elementele exportabile sunt vizibile in mod egal.Daca in doua sau mai

multe biblioteci DLL exista date care au fost denumite cu acelasi iden-

tificator,apar fenomene de supraincarcare sau conflicte de identificator.

Daca nu detineti fila sursa a tuturor filelor DLL,depanarea unui astfel

de program este extrem de dificila sau chiar imposibila.Acest gen de

situatie a fost denumit "DLL HELL" (infernul DLL-urilor).In aceste situ-

atii,in timpul executiei se va returna fie un mesaj de eroare,fie o

valoare eronata preluata din prima biblioteca linkata in care exista o

definitie valabila.In plus,alocarea de memorie de operare se va face dupa

un alt algoritm decat cel proiectat si pot interveni diverse tipuri de

incompatibilitati,suprascrieri,supraincarcari etc.Din acest motiv este

bine sa nu utilizati file DLL pentru care nu detineti si fila sursa,

sa nu utilizati excesiv de multe file DLL in spatiu de memorie limitat,

sa verificati cu atentie memoria libera in urma fiecarui apel posibil,din

fiecare fila,cat si al tuturor combinatiilor posibile de apel intersectat

al mai multor biblioteci.Acest gen de programare,incepe sa semene tot

mai mult cu un joc de tipul "PronoExpres" si nu se recomanda decat celor

cu notiuni avansate de gestionare a memoriei.Lucrurile se simplifica

foarte mult daca utilizati programe automate de gestioanre si analiza a

memoriei.Acest gen de programe vor apela si evalua toate apelurile posi-

bile si vor semnala eventualele incompatibilitati.Regula de aur este urma-

toarea: " nu va lansati in operatii pe care nu puteti sa le controlati cu

resursele proprii".O solutie extrem de simpla pentru evitarea conflictelor

de identificator este sa utilizati spatii denumite ("namespace") in edita-

rea bibliotecilor.In acest fel,puteti avea un spatiu special pentru toate

bibliotecile DLL editate de d-voastra,care nu va interfera cu celelalte

biblioteci DLL programate de alti programatori.Pentru importul datelor

utilizati si formula "using namespace NUMELE" (vezi si inceputul capito-

lului).Visual C++ utilizeaza un astfel de spatiu standardizat denumit

std.Pentru aplicatiile d-voastra puteti utiliza un astfel de standard,cu

un numa cat mai discriminativ (eventual numele si prenumele personal).

Nu va lansati in procese sofisticate de "depanare" a filelor DLL cu

provenienta nesigura sau necunoscuta.Daca exista orice fel de suspiciuni

este mai usor sa abandonati biblioteca respectiva si sa editati una noua.

Atunci cand actualizati o fila DLL,trebuie sa aveti in vedere ca mo-

dificarea efectuata va interesa toate aplicatiile care utilizeaza fila

respectiva.De cele mai multe ori,este preferabil sa pastrati fila veche

si a creati si o noua fila care contine toate modificarile necesare.Astfel

fiecare aplicatia va putea apela fila DLL necesara.

Daca realizati si distribuiti biblioteci DLL,este bine sa distribuiti si

fila sursa (fila .cpp din care a fost creata).Este un obicei bun sa ada-

ugati fila .cpp in proiect,impreuna cu fila dll.dll (la fel ca in exemple-

le prezentate).De obiecei fila sursa este destul de mica si nu ocupa prea

mult spatiu.Nu este bine sa includeti file header in filele DLL decat daca

este absolut necesar.Nu are rost se creati o fila DLL de tip Windows in

care sa includeti fila "windows.h" doar pentru a defini o clasa sau o

functie care realizeaza operatii elementare.Fiecare byte conteaza.Fila DLL

poate contine insa,nelimitate operatii cu vizibilitate locala.


-56-

Fila de tip DLL se compileaza si se construieste la fel ca orice fila

executabila.Exista si biblioteci cu legare dinamica,care au alta extensie

decat .DLL(Exemple: .EXE sau .drv).Pentru aplicatiile Windows,filele DLL

pot fi incarcate si explicit,cu functia LoadLibrary(),urmata de GetProc-

Address() pentru a obtine adresa functiei dorite si de FreeLibrary()

pentru eliberarea memoriei.

Biblioteca DLL poate contine functii interne si poate sa execute o

serie de operatii,la fel ca orice program executabil.Nu se recomanda

utilizarea acestei facilitati decat pentru operatii indispensabile.In

restul situatiilor,se pot utiliza module de program independente,care pot

fi puse in executie cu functii usor de apelat (fara incarcarea memoriei):

EXEMPLU WINDOWS: (vezi si cplus36.cpp)

#include

#include

#include

main()

{

WinExec("cplus2.exe",5);

getch();

return 0;

}

EXEMPLU C++ : (vezi si cplus37.cpp)

#include

#include

#include

main()

{

cout << "text din fila cplus37 \n";

cout << "urmeaza apelul modulului cplus2.exe: \n";

system("cplus2.exe");

getch();

return 0;

}

Pentru programele recente,se recomanda utilizarea functiilor moderne,gen

CreateProcess(),etc.

Bibliotecile DLL pot fi utilizate pentru a arhiva filele de resurse.

In acest caz,la crearea proiectului se va utiliza AddNode pemtru a include

in proiect toate filele de tip .RC necesare.Dupa compilare,rezulta o fila

DLL.Fila DLL poate fi manipulata monobloc,pentru a asigura toate resursele

necesare pentru interfata grafica: meniuri,icons,imagini,sunete etc.

O alta aplicatie frecventa o reprezinta suportul multilingual.Pentru

fiecare limba oferita se distribuie si fila DLL necesara,in care sunt

incluse toate particularitatile versiunii respective.

In mod similar,se creaza si distribuie resursele software necesare

pentru implementarea si exploatarea unor resurse hardware.In acest caz,

de obicei filele vor avea extensia .drv,dar exista si drivere cu extensia

clasica .dll.

O privire sintetica asupra acestui capitol,atrage atentia asupra posi-

bilitatilor de suprastructurare a aplicatiilor si programelor realizate de

d-voastra.Prezentarea nu este exhaustiva,este doar un pretext pentru a va

stimula dorinta de a lectura si alte manuale de specialitate.


-57-

BIBLIOTECA OWL (Object Windows Library)
Biblioteca OWL contine un set de 125 de file header,in care sunt defi-

nite clase si constante,utile pentru a realiza programe si aplicatii ce

utilizeaza o intefata grafica formata din obiecte de tip Windows.OWL este

o alternativa pentru API-Windows (API exploateaza fila windows.h).

Biblioteca OWL nu este prezenta in toate versiunile de C++.In Visual C++

a fost inlocuita prin MFC(Microsoft Foundation Classes) iar in versiunea

C++ Builder a fost inlocuita prin VCL(Visual Component Library).

In esenta,toate aceste variante realizeaza acelasi lucru: definesc o

serie de clase,din care se vor deriva obiectele necesare pentru a realiza

o interfata grafica.Fiecare obiect,detine unul sau mai multi constructori,

un destructor si o serie de metode proprii specializate.

Versiunea Borland C++ 5.A,nu contine explicatii destul de clare despre

modul in care poate fi utilizata aceasta biblioteca,dar contine o serie

destul de bogata de exemple si programe si un tutorial destul de clar (in

directorul Examples/Owl).Exemplele si obiectele nu sunt compilate si

link-ate.Pentru a putea utiliza aceste exemple,deschideti proiectul,apoi

construiti fiecare nod cu BuildNode(click drept de mouse) si in final

asigurati legaturile dintre modulele componente executand un click de

mouse drept pe fila de tip .exe si selectand optiunea Link.Executati apoi

fiecare exemplu si aplicatie sau program si observati modul in care au

fost realizate.Fiecare dintre aceste exemple si programe poate reprezenta

punctul de plecare pentru un program realizat de d-voastra.Un tutorial

foarte bun si o serie de informatii utile despre OWL se gasesc si la

adresa: http://owlnext.

Cea mai simpla aplicatie posibila este deschiderea unei ferestre de tip

Windows:

EXEMPLU: (vezi si OWL_ABC / owl1)

Deschideti un nou proiect,cu New si Project.Eliminati fila .rc si cea .def

cu DeleteNode,apoi adaugati cu AddNode fila default.def din directorul

LIB si o fila de tip .rc care contine urmatorul text:

#include

#include

#include

Apoi deschideti fila de tip .cpp si introduceti urmatorul text:

#include

#include
int

OwlMain(int, char* [])

{

return TApplication("Titlul Ferestrei !").Run();

}

Compilati,construiti nodul cu build node,apoi selectati fila .exe,constru-

iti nodul cu Build Node si adigurati legaturile cu Link (dupa click drept

de mouse).Proiectul este finalizat si poate fi executat.

Un exercitiu identic este si la adresa Examples\Owl\Apps\Hello.

Puteti utiliza direct exercitiul "Hello" ca punct de pornire.Nu trebuie

decat sa schimbati textul pentru titlul ferestrei.In general,nu trebuie

sa evitati sa folositi modulele realizate anterior.


-58-

Daca analizam putin exemplul de mai sus,observam ca include doua file

header,dupa care apeleaza functia Run() pentru un obiect de tip TAppli-

cation(functia Run() apeleaza constructorul clasei,care realizeaza un

obiect din tipul respectiv).

Biblioteca contine definita clasei TApplication.Nu

exista in manualul Help o descriere a claselor de obiecte din OWL,astfel

incat va trebui sa va obisnuiti sa lucrati direct cu fila header,sau sa

extrageti pe niste planse toate obiectele impreuna cu definitia lor.

Daca deschideti fila "applicat.h" (din INCLUDE\OWL) observati ca printre

alte definitii,contine si definitia pentru clasa TApplication.

In rezumat,definitia este cam asa:

class _OWLCLASS TApplication : virtual public TEventHandler

public Tmodule

public TMsgThread

{ public:

TApplication( ...parametrii primului constructor...);

TApplication( ...parametrii constructorului secund...);

~TApplication();

....o serie de functii Get si Set

CanClose();

Run();

Start();

}

Asadar,clasa TApplication mosteneste clasele TEventHandler,TModule si

TMsgThread,are doi constructori,un destructor si o serie de metode,dintre

care se disting: Run(),CanClose() si Start().

Nu este o regula absoluta,dar foarte multe programe au ca punct de

pornire un obiect derivat in clasa TApplication,deoarece prin simpla

apelare a metodei Run() se va apela automat si constructorul implicit al

obiectului.Daca doriti,puteti sa nu utilizati un astfel de obiect,dar

in acest caz va trebui sa apelati explicit fiecare constructor,sa faceti

toate operatiile de initializare si sa gestionati singur si toate opera-

tiile de eliberare a memoriei.Obiectul TApplication,prin destructorul

implicit asigura si eliberarea automata a memoriei.

Observati ca fila "applicat.h" a inclus automat in memorie si filele

header , si necesare

pentru derivarea clasei Taplication si respectiv

necesara pentru definitile generice ale optiunilor de compilare.

Cealalata fila header include automat fila .

Fila "owlcore.h" incarca in memorie principalele file necesare pentru o

aplicatie obisnuita(adica defs.h,module.h,applicat.h,dc.h,menu.h,window.h

mdi.h,mdichild.h,decmdifr.h,dialog.h,control.h).

Pentru exemplul de mai sus,aceste clase nu sunt necesare,astfel incat

se poate renunta la ele.Fila header a fost inclusa in acest

exemplu doar pentru a va atrage atentia ca exista si aceasta optiune.

Fila "pch.h" este foarte comoda,atunci cand incepeti editarea unui proiect

si nu stiti inca exact ce anume doriti sa faceti.Pentru a evita consulta-

rea permaneta a tuturor filelor,puteti utiliza aceasta optinue,sau respec-

tiv fila "owlall.h> care incarca toate filele din biblioteca OWL.Dupa

ce proiectul este finalizat,puteti sa alegeti cu strictete doar filele

strict necesare,astfel incat executabilul construit sa fie cat mai mic.


-59-

Daca va place sa gestionati singur memoria,renuntati la si

includeti doar filele strict neceare.Construiti executabilul si faceti

comparatia pentru volumul de memorie consumata.Pentru programele mari,

difernta va fi din ce in ce mai nesemnificativa si va fi mai simplu sa

apelati direct "owlall.h".Decizia este in functie de dimensiunea memoriei

de RAM a hard-ului instalat si in functie de importanta programului,sau

in functie de mediul de operare in care lucrati (ce alte programe ruleaza

in paralel).Pe cat posibil se va cauta intotdeauna solutia cea mai eco-

nomica (mai ales daca utilizati mai multe programe in paralel).

Primul program,este extrem de simplu,dar nu lasa prea mult loc pentru

dezvoltare.Se pot utiliza si functiile Start() pentru a efectua o serie

de operatii pregatitoare inainte de a apela constructorul,sau respectiv

CanClose(),pentru a executa o serie de operatii inainte de a apela des-

tructorul.Prin inchiderea ferestrei(cu butonul x),destructorul este

apelat automat si se efectueaza eliberarea automata a memoriei.

Pentru a putea introduce o serie intrega de functii si proceduri noi,

fereastra generata automat de catre constructorul implicit trebuie sa

fie redefinita.Pentru acest scop se va deriva o clasa de tip TFrameWindow

in care se pot apoi introduce procedurile specifice:

EXEMPLU: (vezi si OWL_ABC / owl2 )

Deschideti un proiect nou,ca mai sus,dar in fila .cpp introduceti un text

de genul:

#include

#include

#include

class Fer1 : public TWindow {

public:

Fer1(); };

Fer1::Fer1() : TWindow(0,0,0) { };

class Aplicatie1 : public TApplication {

public:

Aplicatie1() : TApplication() { };

void InitMainWindow();

};

void Aplicatie1::InitMainWindow()

{

MainWindow = new TFrameWindow(0,"Test",new Fer1);

}

int

OwlMain(int, char* [])

{

return Aplicatie1().Run();

}

Compilati,construiti si executati.Rezultatul este identic cu cel din exer-

citiul precedent,adica o fereastra simpla de tip Windows.De aceasta data

insa am materializat un obiect din clasa TApplication si am utilizat o

clasa denumita Fer1,derivata din TWindow,la care am redefinit constructo-

rul.Apoi am utilizat functia InitMainWindow pentru a deschide o fereastra

de tipul Fer1,cu ajutorul constructorului implicit al obiectului de tip

TApplication.Constructia pare complicata,dar este foarte prcatica pentru

redefinirea proprietatilor ferestrei in care vom executa operatii.


-60-

Deschideti fila "framewin.h" si observati definitia pentru clasa _OWLCLASS

TFrameWindow (are un numar foarte mare de metode implicite).

Fila a fost inclusa automat de ,dar a fost

specificata si explicit pentru a va atrage atentia asupra acestei file.

In continuare,se pot defini noi metode pentru fereastra Fer1.

EXEMPLU: (vezi si OWL_ABC / owl3)

Deschideti un nou proiect,iar in fila .cpp introduceti un text de genul:

#include

#include

#include

#include

class Fer1: public TWindow {

public:

Fer1();

void EvLButtonDown(uint, TPoint&);

void EvRButtonDown(uint, TPoint&);

DECLARE_RESPONSE_TABLE(Fer1); };

DEFINE_RESPONSE_TABLE1(Fer1,TWindow)

EV_WM_LBUTTONDOWN,

EV_WM_RBUTTONDOWN,

END_RESPONSE_TABLE;

Fer1::Fer1():TWindow(0,0,0) { };

void Fer1::EvLButtonDown(uint,TPoint& point)

{

TClientDC dc1(*this);

dc1.Rectangle(point.x-50,point.y-50,point.x+50,point.y+50);

dc1.TextOut(point,"Text:",5);

};

void Fer1::EvRButtonDown(uint,Tpoint&)

{

MessageBox("Butonul drept a fost apasat !","Text:",MB_OK);

};

class Aplicatie1 : public TApplication {

public:

Yüklə 1,36 Mb.

Dostları ilə paylaş:
1   ...   5   6   7   8   9   10   11   12   ...   18




Verilənlər bazası müəlliflik hüququ ilə müdafiə olunur ©muhaz.org 2024
rəhbərliyinə müraciət

gir | qeydiyyatdan keç
    Ana səhifə


yükləyin