webForumDet fria alternativet

Tvåvägskommunikation mellan klasser?

C/C++

8 svar · 344 visningar · startad av Andreas L

Medlem sedan sep. 2000215 inlägg
Frågan#1

Frågan är enkel:
Hur skapar jag tvåvägskommunikation mellan två klasser. Det fungerar fint att skapa en relation på ena hållet: pekare mot önskad klass och sedan koppla ihop dem i någon funktion.

Men jag kan inte hitta något exempel (kod) på nätet för hur jag på ett enkelt sätt skapar en dubbelsidig kommunikation?

ex. ett företag och en personklass.
En pekare som array (flera till en) pekar på person, och en person hamnar på något index i arrayen.
-Fungerar fint, och jag kan enkelt lista olika personer som tillhör ett visst företag.

Men, jag vill även att ifrån personobjektet får reda på var denne "arbetar".

Någon som har eller känner till ett exempel(kod) på hur jag skriver i de olika klasserna för att få kommunikationen dubbelriktad?

*hoppas på svar*

Medlem sedan sep. 2000215 inlägg
#2

nuvarande kod...

följande fungerar som tänkt, men jag vill även ifrån personklassen kunna ta reda på vilket företag denne jobbar på.

HUR skapar jag dubbelriktad kommunikation?


#include <iostream>
#include <string>

using namespace std;
//******************************************
class person{
	public:
		person(){name = "nisse";}
		string showPerson(){return name;}
	private:
		string name;
};
//******************************************
class foretag{
	public:
		foretag()
		{fnamn = "hej och hå";}
		void relateraPerson(person &pers)
		{ p[2] = &pers;}
		string visaPerson(int index){
		return p[index]-> showPerson(); }
	private:
		string fnamn;
		person *p[10];
};
//******************************************
int main(){
	string a;
	person p;
	foretag f;

f.relateraPerson(p);//accocierar person med företag

cout << f.visaPerson(2) << endl; //visar given person på företaget

cout << "press return to exit program" << endl;
getline(cin,a);

return 0;
}
Medlem sedan sep. 20011 086 inlägg
#3

Gissar att ditt problem är att du inte kan deklarera en foretag* i person?
Det löser du genom att göra en forward-deklaration, nåt sånt här

class foretag;  //forward-declaration
class person
{ /* här kan du deklarera foretag* variabler */ };
class foretag
{ /* som innan */ }
Medlem sedan sep. 2000215 inlägg
#4

Eh...

Tack för tipset.

Nu tycker ni kanske att jag blir tjatig, men problemet för mig uppstår när jag ska skapa en funktion för att kunna returnera företagets namn ifrån personklassen. Det fungerar ju ifrån andra hållet, att få reda på vilken/vilka personer som tillhör klassen. Men när jag försöker att skriva likadant för att göra samma sak ifrån personklassen så får jag inte det... ;(

Så här ser koden ut. Den är klar att köra om någon skulle vilja prova. Kanske är det så att jag angriper det på fel sätt, men jag vet inte hur...

#include <iostream>
#include <string>

using namespace std;
//******************************************
class foretag;
class person{
	public:
		person(){name = "nisse";}
		string showPerson(){return name;}
		
		void relateraForetag(foretag &foret)
		{ff = &foret;}//personen återkopplas till företag. anropas ifrån foretag-class
		
		string vilketForetag(){
			//här blir det fel. men det fungerar omvänt från företagslkassen
			//att hämta namn ifrån personklassen
			return ff-> visaForetag();
		}

	private:
		string name;
		foretag *ff;
};
//******************************************
class foretag{
	public:
		foretag()
		{fnamn = "hej och hå";}
		
		void relateraPerson(person &pers, foretag f)
		//borde man inte kunnan använda "this" istället för att ange "f"
		{ p[2] = &pers;
		//anropar personklassen och gör en motkoppling 
			pers.relateraForetag(f);
		}
		string visaPerson(int index){
			return p[index]-> showPerson(); //fungerar
		}
		string visaForetag(){
			return fnamn;
		}
	private:
		string fnamn;
		person *p[10];
};
//******************************************
int main(){
	string a;
	person p;
	foretag f;

f.relateraPerson(p,f);//accocierar person med företag

cout << f.visaPerson(2) << endl; //visar given person på företaget
cout << f.visaForetag() << endl;

cout << "press return to exit program" << endl;
getline(cin,a);

return 0;
}

Hoppas att någon kunnig person kan hjälpa mig att lösa detta!

Medlem sedan sep. 20011 086 inlägg
#5

Problemet där är att vid raden return ff-> visaForetag(); så vet kompilartorn endast om att det finns en klass som heter foretag, men inte vad den har för medlemsfunktioner.
Det du får göra är att lägga klassdeklarationerna för sig och implementeringen efter.
Nåt sånt här:

#include <iostream>
#include <string>

using namespace std;
//******************************************
class foretag;
class person{
public:
  person(){name = "nisse";}
  string showPerson();
  
  void relateraForetag(foretag &foret);
  
  string vilketForetag();
  
private:
  string name;
  foretag* ff;
};
//******************************************
class foretag{
public:
  foretag()
  {fnamn = "hej och hå";}
  
  void relateraPerson(person &pers, foretag f);
  
  string visaPerson(int index);
  string visaForetag();

private:
  string fnamn;
  person *p[10];
};

void foretag::relateraPerson(person &pers, foretag f)
{ 
  p[2] = &pers;
  pers.relateraForetag(f);
}

string foretag::visaPerson(int index){
  return p[index]-> showPerson(); //fungerar
}
string foretag::visaForetag(){
  return fnamn;
}

string person::showPerson()
{ return name; }

void person::relateraForetag(foretag &foret)
{ff = &foret;}

string person::vilketForetag(){
  return ff-> visaForetag();
}

//******************************************
int main(){
        string a;
        person p;
        foretag f;

f.relateraPerson(p,f);//accocierar person med företag

cout << f.visaPerson(2) << endl; //visar given person på företaget
cout << f.visaForetag() << endl;

cout << "press return to exit program" << endl;
getline(cin,a);

return 0;
}

(Koden fungerar att kompilera med gcc och köras).

Lite andra tips, ofta lägger man klassdeklarationerna i en .h-fil och sen implementationen i en .cpp-fil (eller .cc-fil, kvittar vilket).

Hade jag gjort det här själv så hade jag nog låtit vilketForetag() (i person) returnera ett foretag-objekt istället för en string. Samma sak med visaPerson() (i foretag), den borde returnera ett person-objekt.

Sen kan man öka prestandan (väldigt lite i det här fallet, ska jag medge) genom att skriva konstruktorerna såhär istället

foretag() :fnamn("hej och hå") {}

person() : name("nisse") {}
Medlem sedan sep. 2000215 inlägg
#6

Ett jättestort tack för att du tagit dig tid att kika på mitt problem. Lite lustigt är att jag skrev allt i samma fil, utan att dela upp definition och implementation för att göra det lite enklare att labba med. Blev visst tvärt om?!

Blev först lite orolig när jag fick körningsfel då jag försökte anropoa p.vilketForetag() men det visade sig att jag var tvungen att ändra:

void foretag::relateraPerson(person &pers, foretag f)

till

void foretag::relateraPerson(person &pers, foretag &f)

Det fungerar!
Tack!

Medlem sedan juli 2002581 inlägg
#7

Varför skickar du med ett foretag& till relateraperson?

Det är ju en medlemsfunktion, så det känns fel att skicka med förtaget en extra gång.

Medlem sedan juli 2002581 inlägg
#8

Så här alltså:

class Person;
class Företag;

class Person
{
public:
  void relateraFöretag(Företag* f)
  {
     företag = f;
  }
protected:
  Företag* företag;
};

class Företag
{
public:
  void relateraPerson(Person* p)
  {
    p->relateraFöretag(this);
    personer[2] = p;
  }
private:
  Person* personer[10];
};
Medlem sedan sep. 2000215 inlägg
#9

Jodå...

Sang-drax
Jo, jag var inne på det innan oxå, om det inte skulle gå att använda "this" för att hänvisa till det aktuella objektet.

Ser onekligen väldigt snyggt ut som du skrivit, och jag ska kolla närmare på det, med ett par implementerade funktioner!

Tack (så länge..) !!!
:)

392 ms totalt · 4 externa anrop · v20260731065814-full.e96017d9
125 ms — deklarationer (db)
122 ms — hämta statistik (db)
139 ms — hämta tråd, inlägg och bilagor (db)
129 ms — ändringar (db)