Page 1 of 1

[C++] Cum evit includerile circulare?

Posted: 02 Aug 2007, 13:21
by Marius Bancila
Intrebare: Am doua clase, sa le zicem foo si bar, si fiecare contine pointeri la cealalta, astfel incat fiecare header il include pe celalalt. Cand compilez, apar diverse erori. Cum pot scapa de ele?

Raspuns: Sa zicem ca cele doua clasa arata asa:

Code: Select all

// foo.h
#pragma once
#include "bar.h"

class foo
{
	bar* objBar;
public:
	foo(void);
	~foo(void);

	void SetBarPtr(bar* b);
};

// foo.cpp
#include "foo.h"

foo::foo(void)
{
}

foo::~foo(void)
{
}

void foo::SetBarPtr(bar* b)
{
	objBar = b;
}
respectiv

Code: Select all

// bar.h
#pragma once
#include "foo.h"

class bar
{
	foo* objFoo;
public:
	bar(foo* f);
	~bar(void);
};

// bar.cpp
#include "bar.h"

bar::bar(foo* f):objFoo(f)
{
}

bar::~bar(void)
{
}
Solutia pentru aceasta problema a erorilor datorate includerilor circulare este folosirea declaratiilor forward, dar aceasta nu este posibila decat atunci cand se folosesc pointeri sau referinte. Declaratie forward inseamna ca se declara doar numele tipului, ceea ce creaza un tip imcomplet. Acesta va deveni complet in momentul cunoasterii declaratiei complete (prin includerea fisierului in care aceasta este facuta).

Code: Select all

// foo.h
#pragma once

class bar; // declaratie forward

class foo
{
	bar* objBar;
public:
	foo(void);
	~foo(void);

	void SetBarPtr(bar* b);
};

// foo.cpp
#include "foo.h"
#include "bar.h" // includere header pentru bar

foo::foo(void)
{
}

foo::~foo(void)
{
}

void foo::SetBarPtr(bar* b)
{
	objBar = b;
}
respectiv

Code: Select all

// bar.h
#pragma once

class foo; // declaratie forward
class bar
{
	foo* objFoo;
public:
	bar(foo* f);
	~bar(void);
};

// bar.cpp
#include "bar.h"
#include "foo.h" // includere header pentru foo

bar::bar(foo* f):objFoo(f)
{
}

bar::~bar(void)
{
}
Atentie: Dupa cum am mentionat mai sus, aceasta solutie este posibila doar atunci cand se folosesc pointeri sau referinte la aceste tipuri incomplete (introduse prin declaratiile forward). Motivul este ca pentru a putea efectua compilarea, compilatorul trebuie sa cunoasca dimensiunea tipul obiectului. Aceasta nu este cunoscuta pentru tipuri incomplete, dar dimensiunea pointerilor si a referintelor este aceiasi, indiferent de tip.


Next FAQ >>