[C++] Care e scopul guard-urilor de include?

Despre limbajul de programare C++ si biblioteca standard STL (forum moderat)
Post Reply
User avatar
Marius Bancila
Fondator
Fondator
Posts: 2344
Joined: 11 Jul 2007, 11:45
Judet: Timiş
Location: Timisoara
Contact:

[C++] Care e scopul guard-urilor de include?

Post by Marius Bancila » 02 Aug 2007, 13:04

Intrebare: Toate fisierele header au continutul incadrat intre cateva instructiuni preprocesor pe structura ifdnef/define/endif. De ce?

Raspuns: Acest lucru este necesar pentru a evita definitiile multiple. Directiva preprocesor #include va determina pre-compilatorul sa inlocuiasca respectiva linie de cod cu continutul intregului fisier (exact cum se intampla cu macro-urile). Probleme pot apare in situatii precum cea descrisa mai jos:

Fie fisierul foo.h in care este declarata o clasa foo:

Code: Select all

// foo.h
class foo
{
};
Acesta clasa e derivata de bar1 si bar2, fiecare cu propria pereche de fisiere h/cpp:

Code: Select all

// bar1.h
#include "foo.h"

class bar1: public foo
{
};

Code: Select all

// bar2.h
class bar2: public foo
{
};
Cele doua clase bar1 si bar2 sunt ambele folosite intr-un fisier cpp, sa zicem cel care contine functia main. In acest caz cele 2 headere trebuie ambele incluse

Code: Select all

// main.cpp
#include "bar1.h"
#include "bar2.h"

int main()
{
}
In faza de precompilare, directivele #include sunt inlocuite, astfel incat se ajunge la:

Code: Select all

// main.cpp
// bar1.h
// foo.h
class foo
{
};

class bar1: public foo
{
};

// bar2.h
// foo.h
class foo
{
};

class bar2: public foo
{
};

int main()
{
}
La compilarea lui main.cpp clasa foo va fi gasita ca fiind definita de 2 ori. Solutia este adaugarea unor directive care sa evite includerea continutului unui fisier de 2 ori:

Code: Select all

// foo.h
#ifndef _FOO_
#define _FOO_

class foo
{
};

#endif // _FOO_
(Desigur aceasta trebuie facut pentru toate fisierele header.)

In acest caz la prima includere _FOO_ nu este definit astfel incat va fi definit si tot ce urmeaza pana la #endif va fi inclus. La includerile consecutive, fiindca _FOO_ este definit deja, nu se va mai include nimic.


Intrebare: Poate fi acelasi efect obtinut si altfel?

Raspuns: Compilatoarele Microsoft ofera o directiva pragma numita 'once' care are exact acelasi efect. Aceasta solutie nu este insa portabila, pentru ca alte compilatoare nu o recunosc.

Code: Select all

//foo.h
#pragma once

class foo
{
};

Next FAQ >>


Marius Bancila
Fondator Codexpert, Microsoft MVP VC++
Site personal | Blog

Post Reply