Archief - [PROG][C++] Header loading loop

Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.

jodeman

Legacy Member
Het probleem is dat ik in twee klasse's #include doe en dat de compiler vastzit in een include loop.
Hoe kan ik dat voorkomen?

Thanks.

The Crazy Frog

Legacy Member
Code:
#pragma once
...
Doet hetzelfde als die define, maar is minder typwerk.

killgore

Legacy Member
The Crazy Frog zei:
Code:
#pragma once
...
Doet hetzelfde als die define, maar is minder typwerk.

en is compiler-afhankelijk, de bovenstaande oplossing werkt op elke ansi/iso compiler.

jodeman

Legacy Member
oh damn, dan is het nog iets anders, want dat gebruik ik al.
Zal morgen meer informatie proberen posten over het probleem.

Tyfius

Legacy Member
Je kan altijd eens een stuk van je code posten, misschien maak je ergens een fout.
De volledige juiste error die de compiler geeft kan ons ook altijd helpen.

killgore

Legacy Member
jodeman zei:
oh damn, dan is het nog iets anders, want dat gebruik ik al.
Zal morgen meer informatie proberen posten over het probleem.

zorg dat ook includes binnen die #ifndef staan he ;).

jodeman

Legacy Member
Ja, alles staat binnen ifndef normaal. Hier is de source.
Wanneer ik bij dealer die table uitcomment krijg ik volgende error.
Als ik dat weglaat compiled het gewoon.

1>Dealer.cpp
1>c:\documents and settings\jiggy\my documents\platforms\visual studio 2005\projects\pokerengine\pokerengine\table.h(29) : error C2143: syntax error : missing ';' before '*'
1>c:\documents and settings\jiggy\my documents\platforms\visual studio 2005\projects\pokerengine\pokerengine\table.h(29) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\documents and settings\jiggy\my documents\platforms\visual studio 2005\projects\pokerengine\pokerengine\table.h(29) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\documents and settings\jiggy\my documents\platforms\visual studio 2005\projects\pokerengine\pokerengine\table.h(29) : warning C4183: 'get_dealer': missing return type; assumed to be a member function returning 'int'
1>c:\documents and settings\jiggy\my documents\platforms\visual studio 2005\projects\pokerengine\pokerengine\table.h(40) : error C2146: syntax error : missing ';' before identifier 'my_dealer'
1>c:\documents and settings\jiggy\my documents\platforms\visual studio 2005\projects\pokerengine\pokerengine\table.h(40) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\documents and settings\jiggy\my documents\platforms\visual studio 2005\projects\pokerengine\pokerengine\table.h(40) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int

Code:
#ifndef DEALER_H
#define DEALER_H

#include "Deck.h"
//#include "Table.h"

class Dealer {
public:
	Dealer();
	~Dealer();

	void init();
	void deal();
	void shuffle();
private:
	//Table my_table;
	Deck my_deck;
};

#endif

Code:
#ifndef TABLE_H
#define TABLE_H

#include <map>

#include "Player.h"
#include "Dealer.h"

class Table {
public:
	enum State {
		STARTING,
		FLOP,
		TURN,
		RIVER,
		END
	};

	Table();
	~Table();

	void initialize();
	void start_game();

	void register_player(Player* p);
	void remove_player(int number);

	Player * get_player(int number);
	Dealer * get_dealer();

	std::map<int,Player> * get_players();
private:
	int pot_total;
	int round_total;
	int raise;
	int small_blind;

	void find_dealer();

	Dealer my_dealer;
	std::map<int,Player> my_players;
};
#endif

killgore

Legacy Member
Vrij hilarisch, kben ook bezig (for fun) me poker dingske, komt wrsch omda da zo popy is tegenwoordig.

Hmpf, een basisfout was wel al (heb je uncommented): je hebt een instantie Dealer in de klasse Table en vice-versa, dat werkt niet echt :p. Normaal gezien gaat hij dan (@runtime) objecten blijven creëren. Dealer is trouwens niet meer dan een speciaal soort speler (ik heb zelfs geen aparte Dealer class for now).

Het is vrij duidelijk dat hij het type Dealer hier niet herkent of dat je toevallig nog een functie Dealer of zo hebt ... .

Zeker dat headers op juiste plaats zitten en zo? edit: en dat je DEALER_H niet per ongeluk ergens definieert :p?

jodeman

Legacy Member
kunt ge dan nooit aan een methode het object 'this' meegeven in c++?
heb het altijd als ik een include doe in de één klasse en vica versa met dezelfde klasse.
Je zegt ook dat die objecten gaat blijven creëeren. Dat was mij al opgevallen dat ik objecten niet moest instantiëren, die moeten gewoon in headers staan en worden geinstantieerd? Gaat de compiler objectvariabelen instantieren bij het laden met de default constructor?
Hoe kan ik dat dan oplossen? Heb dat soms wel nodig. C++ is nogal nieuw voor mij.

van die dealer, weet het :). is nog een oude versie.
heb nu -> deck, player is een deck, dealer is een player

KeaTs

Legacy Member
Dealer include table, table include dealer. That's a no-go, der moet altijd eentje eerst kunnen zijn :)

Oplossing: gebruik forward declarations. Vb in Dealer.h ipv #include "Table.h" te doen doe je class Table; Als'k mij ni vergis moet je dan wel in Dealer een pointer naar Table bijhouden ipv een object zelf, ben echt niet meer gewend aan objecten recursief aggregeren zonder pointer :p

killgore

Legacy Member
jodeman zei:
kunt ge dan nooit aan een methode het object 'this' meegeven in c++?
Natuurlijk wel, wat in principe niet gaat (maar uw compiler zal dat wel oplossen) is dit:

Code:
class A
{
    B b;
};

class B
{
    A a;
}
Aangenomen natuurlijk dat ze van elkaars bestaan afweten.

Neem nu het geval dat we de constructor van A oproepen, deze gaat dan een object van B initialiseren met de standaardconstructor.
Deze gaat op zijn beurt een object van A initialiseren met de standaardconstructor.
En dan deze weer ...
--> oneindige lus :p.

Dat was wat ik bedoelde.

heb het altijd als ik een include doe in de één klasse en vica versa met dezelfde klasse.

Hm, tis uiteindelijk wel logisch, ksnap het al, jij doet dit:
Je include bovenaan in dealer.h het bestand table.h, dus hij gaat die code daar vervangen door de code in table.h.
Nu, dan kom je daar met het probleem dat table.h gaat proberen Dealer.h te includen, dit zal echter nooit gebeuren (nuja, eigenlijk wel, maar ze gaan nooit code inlezen) door die ifndef.

Daardoor komt de declaratie van de klasse Dealer daar pas NA de klasse Table en weet Table dus niet van zijn bestaan waardoor je een fout krijgt :).
Deze dus niet dubbel linken is de oplossing, als je dit wel moet doen heb je vaak een slecht design ;). Edit: je kan het zoals Keats zegt met expliciete definitie doen ook.

edit2: als je persé een table per player wilt bijhouden doe je dit best per pointer.

Je zegt ook dat die objecten gaat blijven creëeren. Dat was mij al opgevallen dat ik objecten niet moest instantiëren, die moeten gewoon in headers staan en worden geinstantieerd? Gaat de compiler objectvariabelen instantieren bij het laden met de default constructor?
Yup, als je met men bovenste code een object van A aanmaakt gaat deze de default constructor aanroepen en deze gaat op zijn beurt de default constructor van B oproepen :).

KeaTs

Legacy Member
om te illustreren wa ik wil zeggen, dit:

class A
{
B b;
};

class B
{
A a;
}


compilet niet, wat je moet doen is:

class B;

class A{
B * b;
};

class B{
A * a;
}

de objecten zelf kan je aanmaken & gebruiken in de .cpp, daar ga je dat probleem niet hebben.

Tyfius

Legacy Member
Ik ben ook verre van een expert, maar als jij dit wilt doen dan zit er een fout ik je design logica.
Een tafel moet weten welke dealer hij heeft, maar een dealer hoeft niet te weten aan welke tafel hij moet delen. In de klasse Table voorzie je dus een dealer object, maar in de klasse Dealer is er geen enkele reden waarom je de klasse Table moet includeren.

Daarnaast is een dealer ook geen Player. Ik dacht aan het volgende:

Code:
#ifndef DEALER_H
#define DEALER_H 1 /*!< To avoid multiple inclusions. */

#include <iostream>

using namespace std;

class Dealer
{
	private:
		Deck my_deck;
		// Eigenlijk ben ik hier geen voorstander van, het gebruik van my_
		
	public:
		Dealer();
		~Dealer();

		// Andere dealer related functies
};

#endif
Code:
#ifndef PLAYER_H
#define PLAYER_H 1 /*!< To avoid multiple inclusions. */

#include <iostream>

using namespace std;

class Player
{
	private:
		string 	player_name;
		double 	money;

	public:
		Player();
		~Player();

		void call();
		void raise();
		void fold();
		void setMoney(double money);
		double getMoney();
};

#endif
Code:
#ifndef TABLE_H
#define TABLE_H 1 /*!< To avoid multiple inclusions. */

#include <iostream>

#include <player.h>
#include <dealer.h>

using namespace std;

#define MAX_PLAYERS_PER_TABLE 4

class Table
{
	private:
		Player playerList[MAX_PLAYERS_PER_TABLE];
		Dealer dealer;

		double 	pot_total;
		double 	small_blind;

		bool 	hasDealer; // Op "false" zetten in de constructor.

	public:
		Table();
		~Table();

		void addPlayer(Player playerToAdd);

		// De variabele "hasDealer" op "true" zetten mocht er nog geen dealer zijn.
		// Een dealer kan maar 1 keer toegevoegd worden!
		void addDealer(Dealer dealerToAdd);
};

#endif
Dit is maar rap bijeen getypt om je een idee te geven. Je kan er normaal wel alles uit afleiden. In de Player klasse kan je eventueel een bool voorzien die een speler verbiedt aan meerdere tafels te spelen.

jodeman

Legacy Member
Ah jawel ;).

Een dealer moet weten aan welke tafel hij zit, omdat hij kaarten moet delen aan de spelers die aan zijn tafel zitten. Ge kunt wel nen dealer verplaatsen van de één tafel naar de ander.

Tyfius

Legacy Member
Jahneen, hij moet niet weten aan welke spelers hij moet delen. Hij moet zelfs niet weten aan welke tafel hij moet delen. De tafel is verantwoordelijk voor het beheer van de spelers en de dealer.

Een dealer heeft een bool "isBusy". Wanneer je in de klasse Table de functie addDealer(object) oproept zet je voor dit Dealer object deze bool op "true". Wanneer je dit object dan aan een ander Table object wilt toewijzen geef je een error terug "Dealer already busy" ofzo. Wanneer je de Dealer van een klasse wilt verwijderen zet je deze bool op "false". Je kan dit Dealer object dan aan een ander Table object toewijzen.
Hetzelfde geld voor de Player objecten. De Table houdt een lijst bij met de Players, maar een Player hoeft niet te weten aan welke tafel hij zit, noch wie zijn Dealer is.

EDIT: Je voorziet dus best ook een klasse "Card". Die bevat de info over de kaart. Een Player is verantwoordelijk voor zijn eigen kaarten en een Table is verantwoordelijk voor de kaarten die gemeenschappelijk zijn (indien het bvb Texas Hold'em is). Een Dealer moet weten welke kaarten er reeds gedeeld zijn en welke er op tafel liggen.

killgore

Legacy Member
jodeman zei:
Ah jawel ;).

Een dealer moet weten aan welke tafel hij zit, omdat hij kaarten moet delen aan de spelers die aan zijn tafel zitten. Ge kunt wel nen dealer verplaatsen van de één tafel naar de ander.

Neen, niet echt, zeker niet in poker, in andere spelletjes ga je dit mssch wel nodig hebben.

De dealer-code implementeer je per table, je moet dan gewoon weten welke speler dealer is om volgorde van delen & binds en zo te bepalen.

Het kan soms wel nuttig zijn om te weten aan welke tafel een speler zit natuurlijk, maar daar houdt je ene pointer (aggregatie) naar de tafel bij, en geen gewoon object (compositie).

jodeman

Legacy Member
Ik zit mijn java toeren te gebruiken in C++ dus daarmee zit ik met zo een code ;).
@ Tyfius : ik heb het anders. Heb een dealer per tafel. Mijn tafel staat puur in om spelers te behandelen en voor pointers naar dealer en actie bij te houden.
Zoals jij het zegt is het gevaarlijk vind ik. Als je at runtime van dealer gaat wisselen ga je mss verkeerde kaarten delen op een verkeerde tafel. Stel nu dat hij niet aan het dealen is en je wijst hem toe aan een andere tafel, dan kan het zijn dat iemand de flop van een andere tafel in zijn hand krijgt.
Heb het zo echt mogelijk gehouden. Een dealer zit aan een tafel en kan enkel kaarten nemen van spelers en teruggeven aan spelers. Heb zelfs bij dealen rekening gehouden dat bvb de 1ste speler van een tafel van 6 de 1ste en 7de kaart krijgt en van die'n shit. Wil het zo echt mogelijk ;).
Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.
Terug
Bovenaan