[C++] problem z przyjacielem


(Jaczula) #1

Mam taki kod (chyba nie wymaga tłumaczenia):

class klasa2;

class klasa1 {

	int int1;

public:

	void func1(klasa2*);

	friend void klasa2::func2(klasa1*);

};

class klasa2 {

	int int2;

public:

	void func2(klasa1*);

	friend void klasa1::func1(klasa2*);

};



void klasa1::func1(klasa2* arg) {

	arg->int2 = 2;

}

void klasa2::func2(klasa1* arg) {

	arg->int1 = 1;

}



int main () {

	klasa1 a;

	klasa2 b;

	a.func1(&b);

	b.func2(&a);

	return 0;

}

Kompilator nie potrafi nadać klasa2::func2 status przyjaciela klasy klasa1. Wiem, że w tamtym momencie jeszcze nie wie, że taka funkcja istnieje, ale nie mam pojęcia, co zrobić, żeby to działało. Z góry dzięki za pomoc.


(Marcin Obala) #2

Przykład ze strony

class klasa

{

  int liczba; // wiadomo, że standardowo składowe klasy są prywatne

  public:

    friend void wyswietl(klasa&); // deklaracja funkcji zaprzyjaźnionej

};


void wyswietl(klasa& kl)

{

  cout << "liczba z klasy to: " << kl.liczba << endl;

}


int main()

{

  klasa kla;

  wyswietl(kla);

  return 0;

}

Działa to tak że deklarując ciało funkcji nie musisz używać operatora zasięgu :: i przypisywać danej funkcji do danej klasy. Funkcja jest globalna a ma dostęp do prywatnych pól klasy dla której jest zaprzyjaźniona. Z tego co zrozumiałem z Twojego kodu to chcesz żeby funkcje miały nawzajem dostęp do prywatnych pól klas ?


(Blapiter) #3

Po pierwsze w tym przykładzie nie jest potrzebne Ci zaprzyjaźnienie i w dodatku odnosisz się do zmiennych prywatnych.

Po drugie:

class klasa2;

class klasa1 

{

	private:

		int int1;   

	public:

		void pokaz();

		void wartosc(int liczba);

		void func1(klasa2*);

};

class klasa2 

{

	private:

		int int2;  

	public:

		void pokaz();

		void wartosc(int liczba);

		void func2(klasa1*);

};



void klasa1::func1(klasa2* arg) 

{

	arg->wartosc(2);

}

void klasa2::func2(klasa1* arg) 

{

	arg->wartosc(1);

}


void klasa1::wartosc(int liczba) 

{

	this->int1 = liczba;

}

void klasa2::wartosc(int liczba)

{

	this->int2 = liczba;

}


void klasa1::pokaz()

{

	cout<int1<
}


void klasa2::pokaz()

{

	cout<int2<
}


template

void pokazowa(TYP & arg)

{

	arg.pokaz();	

}


   klasa1 a;

   klasa2 b;

   a.func1(&b);

   b.func2(&a);

   a.pokaz();

   b.pokaz();

   pokazowa(a);

   pokazowa(b);

(Marcin Obala) #4

Takie ominięcie tego co chciał osiągnąć dodatkowymi funkcjami :wink: Rozwiązanie według mnie dobre jednak z ciekawości samej czy da się zrobić żeby się przyjaźniły te klasy ?


(Blapiter) #5

Tylko pytanie w jakim sensie przyjaźniły ? :slight_smile:

Bo całą istotą klasy jest enkapsulacja, czyli dostęp do jej wartości, idąc dalej bez sensu byłoby jeżeli inna klasa miała dostęp do wartości prywatnej drugiej klasy bezpośrednio :slight_smile:


(Marcin Obala) #6

Ja się zgadzam ale patrząc na kod autora tematu chyba takie było jego założenie. Mi tam to do niczego aktualnie nie potrzebne :wink:


(Jaczula) #7

Wiem, że problem można rozwiązać w inny sposób, jednak powyższy przykład to tylko ćwiczenie. Zależy mi na tym, żeby funkcja w klasie 1 miała dostęp do danych prywatnych klasy 2 i funkcja klasy 2 miała dostęp do danych klasy 1. Rozwiązuję tylko ćwiczenie z książki do nauki c++.


(Blapiter) #8

To w takim razie w klasie1 trzeba zadeklarować że klasa2 będzie jej przyjacielem i na odwrót :

class klasa2;


class klasa1 

{

		int int1;

	public:

		friend class klasa2;

		void func1(klasa2 * arg);

};


class klasa2 

{

		int int2;

	public:

		friend class klasa1;

		void func2(klasa1 * arg);

};



void klasa1::func1(klasa2* arg) 

{

   arg->int2 = 2;

   cout<int2<
}

void klasa2::func2(klasa1* arg) 

{

   arg->int1 = 1;

   cout<int1<
}



   klasa1 a;

   klasa2 b;

   a.func1(&b);

   b.func2(&a);

(Jaczula) #9

@blapiter racja, ale moim założeniem było, żeby przyjacielem klasy 1 była tylko funkcja func2 klasy 2, a nie cała klasa 2. To jest mój problem.

-- Dodane 29.09.2011 (Cz) 18:08 --

ktokolwiek zna odpowiedź?

problem wydaje się prosty, ale powtórzę jeszcze raz: chcę, aby w klasie 1 istniała funkcja, która ma dostęp do prywatnych danych klasy 2 (będąc jej przyjacielem; tylko ta funkcja ma być przyjacielem klasy 2) oraz by w klasie 2 istniała funkcja, która ma dostęp do prywatnych danych klasy 1 (tylko ta funkcja ma być przyjacielem klasy 1)

-- Dodane 08.10.2011 (So) 12:27 --

Jeśli kogoś interesuje, jak to rozwiązać, to niestety nie ma żadnego magicznego słowa, żeby forward declaration funkcji w klasie (member function) było możliwe. Praktycznie trzeba po prostu utworzyć globalną funkcję i "sprzyjacielować" ją z obiema klasami (dostęp do prywatnych danych obu klas).

Jednak ciekawe rozwiązanie (za to nieżyciowe) prezentuje Ralph83 z forum cplusplus.com :

// forward declaration

class X;


// Is a friend of X and provides access to YFuncBase::func(), where func() is implemented.

class YFuncInterface

{

protected:

	static int &getI( X & x );

	// maybe other functions to retrieve private or protected data from X.

};


class X

{

	int i;

public:

	void func();


	friend class YFuncInterface;

};


// Implements func() using functions from YFuncInterface 

// to access protected and private members of X.

class YFuncBase : private YFuncInterface

{

public:

	void func(); // can access X::i through YFuncInterface::getI().

};


// inherits func() from YFuncBase, bot not the access to protected 

// and private members of X. 

class Y : public YFuncBase

{

	int i;

public:

	friend void X::func();

};



// IMPLEMENTATION


int &YFuncInterface::getI( X & x )

{

	return x.i;

}


void YFuncBase::func()

{

	X x;

	getI(x) = 0;

}


void X::func()

{

	Y y;

	y.i = 1;

}