Pagina 1 di 5 1 2 3 ... ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 41
  1. #1

    [c++] ereditarietà e funzioni virtual

    Sto realizzando un programma sul gioco degli scacchi, per rappresentare e movimentare le pedine ho realizzato una classe base ChessPiece e 8 classi derivate, una per ogni tipologia di pezzo(pedoni,re,regina,etc...). La classe base ha un metodo move che è virtual, ho realizzato quindi un metodo move con la stessa signature anche per le derivate.
    La scacchiera è una matrice di puntatori a ChessPiece e alla creazione vengono opportunamente richiamati i giusti costruttori in base al tipo di pezzo (verificato).
    Applico quindi il metodo move su ogni puntatore, però invece di richiamare i metodi delle classi derivate chiama quello della classe base.

    Non so se può influire : le classi Torre e Alfiere sono virtual in quanto da esse deriva la classe Regina, questa scelta è dettata dal fatto che la regina è in grado di muoversi sia come un alfiere che come una torre.

    Non so che parti di codice postare.

  2. #2
    Ho capito dov'è l'errore, ma so spiegarvelo solo a livello sintattico non capisco bene il motivo e non so risolverlo.
    Questa è la chiamata al metodo move:
    game[i][j].move(i,j,game);

    game è la matrice dei puntatori che ho realizzato così
    codice:
    ChessPiece ** Game(char ** cGame) { ChessPiece ** game; game=new ChessPiece *[8]; for(int i=0;i<=7;i++) { game[i]=new ChessPiece[8]; for(int j=0;j<=7;j++) { char piece=cGame[i][j]; switch(piece) { case 'k': { game[i][j]= King(piece); break; } case 'K': { game[i][j]= King(piece); break; } case 'q': { game[i][j]= Queen(piece); break; } case 'Q': { game[i][j]= Queen(piece); break; } case 'b': { game[i][j]= Bishop(piece); break; } case 'B': { game[i][j]= Bishop(piece); break; } case 'r': { game[i][j]= Rook(piece); break; } case 'R': { game[i][j]= Rook(piece); break; } case 'n': { game[i][j]= Knight(piece); break; } case 'N': { game[i][j]= Knight(piece); break; } case 'p': { game[i][j]= Pawn(piece); break; } case 'P': { game[i][j]= Pawn(piece); break; } case '.': { game[i][j]= ChessPiece(); break; } } } } return game; }
    L'errore è che applico move sull'oggetto e non sul puntatore vero?

  3. #3
    Utente bannato
    Registrato dal
    Oct 2010
    Messaggi
    1,219
    Posta il codice completo e non tutto su una riga, copia e incolla l' errore che ti da.
    Al limite se è kilometrico posta le parte più importanti separatamente dal codice completo.

  4. #4
    codice:
    ChessPiece ** Game(char ** cGame)
    {
    	ChessPiece ** game;
    	game=new ChessPiece *[8];
    	for(int i=0;i<=7;i++)
    	{
    		game[i]=new ChessPiece[8];
    		for(int j=0;j<=7;j++)
    		{
    			char piece=cGame[i][j];
    			switch(piece)
    			{
    			case 'k':
    				{
    					game[i][j]= King(piece);
    					break;
    				}
    			case 'K':
    				{
    					game[i][j]= King(piece);
    					break;
    				}
    			case 'q':
    				{
    					game[i][j]= Queen(piece);
    					break;
    				}
    			case 'Q':
    				{
    					game[i][j]= Queen(piece);
    					break;
    				}
    			case 'b':
    				{
    					game[i][j]= Bishop(piece);
    					break;
    				}
    			case 'B':
    				{
    					game[i][j]= Bishop(piece);
    					break;
    				}
    			case 'r':
    				{
    					game[i][j]= Rook(piece);
    					break;
    				}
    			case 'R':
    				{
    					game[i][j]= Rook(piece);
    					break;
    				}
    			case 'n':
    				{
    					game[i][j]= Knight(piece);
    					break;
    				}
    			case 'N':
    				{
    					game[i][j]= Knight(piece);
    					break;
    				}
    			case 'p':
    				{
    					game[i][j]= Pawn(piece);
    					break;
    				}
    			case 'P':
    				{
    					game[i][j]= Pawn(piece);
    					break;
    				}
    			case '.':
    				{
    					game[i][j]= ChessPiece();
    					break;
    				}
    			}
    		}
    	}
    	return game;
    }
    Questa è la chiamata al metodo move:
    game[i][j].move(i,j,game);

  5. #5
    Utente bannato
    Registrato dal
    Oct 2010
    Messaggi
    1,219
    Postalo tutto il codice,compreso quello del main.Sennò come faccio a intuire cosa stai tentando di fare?

  6. #6
    codice:
    #include <iostream>
    using namespace std;
    class ChessPiece
    {
    	
    	public:
    		ChessPiece(){color=-2;type=' ';}
    		int color; //0 black 1white
    		char type;//p:pawn b:bishop r:Rook q:queen k:king n:knight
    		virtual int move(int i,int j,ChessPiece ** game){cout<<endl<<"No Piece moving"<<endl; return -1; }
    };
    
    class King : public ChessPiece
    {
    	public:
    		King::King(char k);
    		int move(int i,int j,ChessPiece ** game);
    };
    
    class Pawn : public ChessPiece
    {
    	public:
    		Pawn::Pawn(char p);
    		virtual int move(int i,int j,ChessPiece ** game);
    
    };
    
    class Rook : virtual public ChessPiece
    {
    
    	public:
    		Rook::Rook(){}
    		Rook::Rook(char r);
    		virtual int move(int i,int j,ChessPiece ** game);
    
    };
    
    class Bishop : virtual public ChessPiece
    {
    	public:
    		Bishop::Bishop(){}
    		Bishop::Bishop(char b);
    		virtual int move(int i,int j,ChessPiece ** game);
    
    };
    
    class Knight : public ChessPiece
    {
    	public:
    		Knight::Knight(char n);
    		virtual int move(int i,int j,ChessPiece ** game);
    
    };
    
    class Queen : public Rook, public Bishop
    {
    	public:
    		Queen::Queen(char p);
    		int move(int i,int j,ChessPiece ** game);
    
    };
    
    ChessPiece ** Game(char ** cGame);
    
    int check(ChessPiece ** game);
    
    #include "header.h"
    #include <string>
    using namespace std;
    
    ChessPiece ** Game(char ** cGame)
    {
    	ChessPiece ** game;
    	game=new ChessPiece *[8];
    	for(int i=0;i<=7;i++)
    	{
    		game[i]=new ChessPiece[8];
    		for(int j=0;j<=7;j++)
    		{
    			char piece=cGame[i][j];
    			switch(piece)
    			{
    			case 'k':
    				{
    					game[i][j]= King(piece);
    					break;
    				}
    			case 'K':
    				{
    					game[i][j]= King(piece);
    					break;
    				}
    			case 'q':
    				{
    					game[i][j]= Queen(piece);
    					break;
    				}
    			case 'Q':
    				{
    					game[i][j]= Queen(piece);
    					break;
    				}
    			case 'b':
    				{
    					game[i][j]= Bishop(piece);
    					break;
    				}
    			case 'B':
    				{
    					game[i][j]= Bishop(piece);
    					break;
    				}
    			case 'r':
    				{
    					game[i][j]= Rook(piece);
    					break;
    				}
    			case 'R':
    				{
    					game[i][j]= Rook(piece);
    					break;
    				}
    			case 'n':
    				{
    					game[i][j]= Knight(piece);
    					break;
    				}
    			case 'N':
    				{
    					game[i][j]= Knight(piece);
    					break;
    				}
    			case 'p':
    				{
    					game[i][j]= Pawn(piece);
    					break;
    				}
    			case 'P':
    				{
    					game[i][j]= Pawn(piece);
    					break;
    				}
    			case '.':
    				{
    					game[i][j]= ChessPiece();
    					break;
    				}
    			}
    		}
    	}
    	return game;
    }
    
    
    int check(ChessPiece ** game)
    {
    	int loser=-1;
    	for(int i=0;i<=7 && loser==-1;i++)
    		{
    			for(int j=0;j<=7 && loser==-1;j++)
    			{
    				if(game[i][j].color!=-2)
    				loser=game[i][j].move(i,j,game);
    			}
    		}
    	
    	return loser;
    }
    
    #include "stdafx.h"
    #include "header.h"
    #include <string>
    #include <iostream>
    using namespace std;
    
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	char ** cGame ;
    	string s1="..k.....ppp.pppp.........R...B..................PPPPPPPPK.......";
    	int i=0;
    	cGame=new char *[8];
    	for (int w=0;w<=7;w++)
    	{
    		cGame[w]=new char[8];
    		for(int k=0;k<=7;k++)
    		{
    			cGame[w][k]=s1[i];
    			cout<<cGame[w][k];
    			i++;
    		}
    		cout<<endl;
    	}
    	i=0;
    	cout<<endl;
    	
    	ChessPiece ** game=Game(cGame);
    	for (int w=0;w<=7;w++)
    	{
    		for(int k=0;k<=7;k++)
    		{
    		
    			cout<<"("<<game[w][k].type<<","<<game[w][k].color<<")";
    			i++;
    		}
    		cout<<endl;
    	}
    	
    	int loser=check(game);
    	
    	switch(loser)
    	{
    		case -1:{cout<<"Game #d: no king is in check."<<endl; break;}
    		case 0:{cout<<"Game #d: black king is in check."<<endl; break;}
    		case 1:{cout<<"Game #d: white king is in check."<<endl; break;}
    		default :{cout<<"prob"<<endl; break;}
    	}
    	cout<<loser<<endl;
    	
    	int a=0;
    	cin>>a;
    	return 0;
    }
    Credo che comunque, come ho scritto in precedenza , il problema stia nella prima porzione di codice che ho postato e in particolare sulla chiamata di move(). Ho fatto delle prove e scrivendo :

    PieceChess * p=new King('k');
    int loser=p.move(i,j,game);

    funziona tutto.

    Invece evidentemente nei metodi check() e game() faccio qualcosa di diverso, ma non capisco bene cosa.
    Scrivendo
    codice:
    ChessPiece ** game;
    	game=new ChessPiece *[8];
    	for(int i=0;i<=7;i++)
    	{
    		game[i]=new ChessPiece[8];
    		for(int j=0;j<=7;j++)
    		{
    			char piece=cGame[i][j];
    			game[i][j]= King(piece);
    					break;
    		}
    }
    int loser=game[0][0].move(0,0,game);
    Cosa cambia rispetto a :
    PieceChess * p=new King('k');
    int loser=p.move(i,j,game);

  7. #7
    Utente bannato
    Registrato dal
    Oct 2010
    Messaggi
    1,219
    Originariamente inviato da superamble
    Credo che comunque, come ho scritto in precedenza , il problema stia nella prima porzione di codice che ho postato e in particolare sulla chiamata di move().
    Il problema era nel metodo game:

    codice:
    int check(ChessPiece ** game)
    {
    	int loser=-1;
    	for(int i=0;i<=7 && loser==-1;i++)
    		{
    			for(int j=0;j<=7 && loser==-1;j++)
    			{
    				if(game[i][j].color!=-2)
    				loser=game[i][j].move(i,j,game);
    			}
    		}
    	
    	return loser;
    }
    Non stavi allocando memoria, ma ti sei corretto tu stesso.
    Quando ci sono porzioni di codice che si chiamano a vicenda non puoi sapere con certezza qual'è la parte che causa il problema, ammenochè non sia una porzione di codice indipendente dalle altre.
    Comunque _tmain non è c++ standard, è fatto dalla Microsoft e ho il serio sospetto che l' unico motivo sia quello di rendere i programmi non portabili su altre piattaforme.
    La funzione main del c++ standard è:

    codice:
    int main(int argc, char** argv)

  8. #8
    Potresti dirmi come correggere?
    Comunque hai postato il metodo Check, confermi che l'errore è in game?

  9. #9
    Il problema è in questo genere di codice:
    codice:
    					game[i][j]= King(piece);
    game è un ChessPiece **, per cui quando scrivi game[i][j] ti trovi ad assegnare un oggetto di tipo King ad uno di tipo ChessPiece.
    In C++ (per una combinazione del fatto che è un linguaggio a tipizzazione statica e con semantica degli oggetti by value) questo uccide il polimorfismo: l'oggetto di tipo King deve essere convertito in un oggetto di tipo ChessPiece, per cui viene invocato il costruttore di copie di ChessPiece che costruisce un ChessPiece sulla base dei dati dell'oggetto che gli viene passato, scartando i dati specifici di King (in particolare il suo tipo e il suo vptr); viene cioè effettuato il cosiddetto "slicing".
    Questo accade perché quando dichiari un oggetto (o un array di oggetti) il suo tipo è completamente fissato (altrimenti il compilatore non saprebbe quanto deve essere grande la variabile, quanta memoria allocare, ...).

    Per preservare il polimorfismo devi memorizzare i tuoi oggetti per puntatore:
    codice:
    ChessPiece *** game;
    // ...
    game[i][k] = new King(piece);
    // eccetera
    questo funziona perché, nonostante il "tipo statico" del puntatore diventi ChessPiece * durante l'assegnamento, l'oggetto in sé viene lasciato in pace, per cui le chiamate ai metodi virtuali vengono risolte correttamente.
    Nota però che usare tutti quei puntatori "liberi" in C++ non è una buona idea, dovresti usare una classe matrice e uno smart pointer per fare sì che i pezzi vengano deallocati correttamente.

    Originariamente inviato da ramy89
    Comunque _tmain non è c++ standard, è fatto dalla Microsoft e ho il serio sospetto che l' unico motivo sia quello di rendere i programmi non portabili su altre piattaforme.
    Io invece ho il serio sospetto che tu non abbia idea del perché si usi _tmain e tutte le altre macro che iniziano per _t.
    Amaro C++, il gusto pieno dell'undefined behavior.

  10. #10
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Originariamente inviato da ramy89
    Comunque _tmain non è c++ standard, è fatto dalla Microsoft e ho il serio sospetto che l' unico motivo sia quello di rendere i programmi non portabili su altre piattaforme.
    Il motivo è un altro, ben più storico e che riguarda UNICODE.
    La serie Win9x si basava su stringhe ANSI, le versioni NT in poi su UNICODE.
    Per evitare che un programmatore impazzisse a cambiare le chiamate API, in modo da adattarle alle varie stringhe, Microsoft ha creato un sistema di macro per astrarre le varie funzioni.
    Giusto per fare un esempio, CreateWindow è definita così:
    codice:
    #ifdef UNICODE
    #define CreateWindowEx CreateWindowExW
    #else
    #define CreateWindowEx CreateWindowExA
    #endif // !UNICODE
    e così tutte le funzioni API che prendono stringhe.
    Per la libc è leggermente diverso:
    codice:
    #ifdef _UNICODE
    #define char TCHAR
    #define strcpy _tcscpy
    #else
    #define wchar_t TCHAR
    #define wcscpy _tcscpy
    #endif // !_UNICODE
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.