[C++] Care e scopul guard-urilor de include?
Posted: 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:
Acesta clasa e derivata de bar1 si bar2, fiecare cu propria pereche de fisiere h/cpp:
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
In faza de precompilare, directivele #include sunt inlocuite, astfel incat se ajunge la:
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:
(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.
Next FAQ >>
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
{
};
Code: Select all
// bar1.h
#include "foo.h"
class bar1: public foo
{
};
Code: Select all
// bar2.h
class bar2: public foo
{
};
Code: Select all
// main.cpp
#include "bar1.h"
#include "bar2.h"
int main()
{
}
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()
{
}
Code: Select all
// foo.h
#ifndef _FOO_
#define _FOO_
class foo
{
};
#endif // _FOO_
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 >>