Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
3.5k views
in Technique[技术] by (71.8m points)

pointers - C++ How to use methods of forward declared classes

I'm doing a console checkers in C++. The problem is I can't refer to methods of forward-declared class.

Here's a header of Board class.

#define BOARD_H
#include "Square.h"
#include <vector>
#include <map>
class Man;

typedef std::vector<Square*> Column;

class Board
{
    const int BOARD_SIZE = 8;
    std::vector<Column> squares;
    std::map<Location, Square*> locationSquareMap; //still kinda secret for me

public:
    Board();
    ~Board();
    //Board(Board& board);
    void printBoard();
    std::map<Location, Square*> getLocationSquareMap();
};

#endif

And it's implementation. Here (printBoard()) I try to access man object via pointer, but I cannot do this because of incomplete type error.

#include "Board.h"

Board::Board() 
{   //white black
    
    for (int row = 0; row < BOARD_SIZE; row++)
    {
        squares.push_back(Column());
        for (int column = 0; column < BOARD_SIZE; column++)
        {
            Location currentLocation(File(column), row);
            SquareColor currentSquareColor = SquareColor::WHITE;
            if ((column + row) % 2 == 0)        //lol the bug was here, forgot about brackets
            {
                currentSquareColor = SquareColor::BLACK;
            }
            Square* currentSquare = new Square(currentLocation, currentSquareColor);
            locationSquareMap.insert(std::make_pair(currentSquare->getLocation(), currentSquare));
            squares.at(row).push_back(currentSquare);
        }
    }   
}

Board::~Board()
{

}

void Board::printBoard()
{
    for (int i = squares.size() - 1; i != -1; i--)
    {
        for (int g = squares.at(i).size() - 1; g != -1; g--)
        {
            std::cout << *(squares.at(i).at(g)) << std::endl;
        }
    }
    std::cout << "    ";
    for (int i = 0; i < BOARD_SIZE; i++)
    {
        switch (File(i))
        {
        case File::A : std::cout << "A "; break;
        case File::B : std::cout << "B "; break;
        case File::C : std::cout << "C "; break;
        case File::D : std::cout << "D "; break;
        case File::E : std::cout << "E "; break;
        case File::F : std::cout << "F "; break;
        case File::G : std::cout << "G "; break;
        case File::H : std::cout << "H "; break;
        default: std::cout << " "; break;
        }
    }
    std::cout << std::endl << std::endl;
    for (int i = squares.size() - 1; i != -1; i--)
    {
        std::cout << i << "   ";
        for(int g = 0; g < squares.at(i).size(); g++)
        {
            Man* currentMan;
            if (squares.at(i).at(g)->getIsOccupied())
            {
                currentMan = squares.at(i).at(g)->getCurrentMan();
                //currentMan->      can't refer to methods 
            }
            else
            {
                std::cout << "_ ";
            }
        }
        std::cout << std::endl;
    }
}

std::map<Location, Square*> Board::getLocationSquareMap()
{
    return locationSquareMap;
}

Man's header:

#ifndef MAN_H
#define MAN_H
#include "ManColorEnum.cpp"
#include "Square.h"
#include <iostream>
#include <string>
#include <vector>
#include "LocationFactory.h"
#include "Board.h"


class Man
{
    ManColor color;
    Square* currentSquare;
    bool isKing;

public:
    Man(ManColor color, Square* square);
    ~Man();
    //Man(Man& man);
    Square* getCurrentSquare();
    void setCurrentSquare(Square* square);
    bool getIsKing();
    void setIsKing();
    ManColor getColor();
    void makeMove(Square* square);
    std::vector<Location> getValidMoves(Board* board);
    friend std::ostream& operator<<(std::ostream& ostream, const Man& man);
};

#endif

Man's .cpp file:

#include "Man.h"

Man::Man(ManColor color, Square* square)
{
    this->color = color;
    this->currentSquare = square;
    this->isKing = false;
}

Man::~Man()
{
    //dtor
}

ManColor Man::getColor()
{
    return color;
}

std::vector<Location> Man::getValidMoves(Board* board)
{
    std::vector<Location> moveCandidates{};
    if (!isKing)
    {   
        Location currentLocation = this->currentSquare->getLocation();
        std::map<Location, Square*> squareMap = board->getLocationSquareMap();
        moveCandidates.push_back(LocationFactory::createLocation(currentLocation, 1, 1)); //move one right forward
        moveCandidates.push_back(LocationFactory::createLocation(currentLocation, -1, 1)); //move one left forward
        moveCandidates.push_back(LocationFactory::createLocation(currentLocation, 2, 2)); //capture forward right
        moveCandidates.push_back(LocationFactory::createLocation(currentLocation, -2, 2)); //capture forward left
        moveCandidates.push_back(LocationFactory::createLocation(currentLocation, 2, -2)); //capture backwards right
        moveCandidates.push_back(LocationFactory::createLocation(currentLocation, -2, -2)); //capture backwards left

        //TODO have to capture
        for (int i = 0; i < moveCandidates.size(); i++)
        {
            //here I filter for moves to exist on the board
            if (squareMap.count(moveCandidates.at(i)) == 0)
            {
                moveCandidates.erase(moveCandidates.begin() + i);
            }
            
            //here I filter occupied squares
            if (squareMap[moveCandidates.at(i)]->getIsOccupied())
            {
                moveCandidates.erase(moveCandidates.begin() + i);
            }

            //here I filter capture moves
            File currentFile = moveCandidates.at(i).getFile();
            int currentRank = moveCandidates.at(i).getRank();
            Square* preSquare = nullptr;

            for (std::map<Location, Square*>::iterator it = squareMap.begin(); it != squareMap.end(); it++)
            {
                //check capture forward right
                if (int(it->first.getFile()) == int(currentFile) + 2 && it->first.getRank() == currentRank + 2)
                {
                    for (std::map<Location, Square*>::iterator itr = squareMap.begin(); itr != squareMap.end(); itr++)
                    {
                        if (int(itr->first.getFile()) == int(currentFile) + 1 && itr->first.getRank() == currentRank + 1)
                        {
                            preSquare = itr->second;
                            break; //check to be careful here
                        }
                    }
                    //if (it->second->getIsOccupied() 
                    //  || (preSquare->getIsOccupied() && preSquare->getCurrentMan()->color == color)
                    //  || (!it->second->getIsOccupied() && !preSquare->getIsOccupied()))
                    //{
                    //  moveCandidates.erase(moveCandidates.begin() + i);
                    //  break; //check to be careful here
                    //}
                }
                //check capture backward right 
                else if (int(it->first.getFile()) == int(currentFile) + 2 && it->first.getRank() == currentRank - 2)
                {
                    for (std::map<Location, Square*>::iterator itr = squareMap.begin(); itr != squareMap.end(); itr++)
                    {
                        if (int(itr->first.getFile()) == int(currentFile) + 1 && itr->first.getRank() == currentRank - 1)
                        {
                            preSquare = itr->second;
                            break;
                        }
                    }
                }
                //check capture forward left
                else if (int(it->first.getFile()) == int(currentFile) -2 && it->first.getRank() == currentRank + 2)
                {
                    for (std::map<Location, Square*>::iterator itr = squareMap.begin(); itr != squareMap.end(); itr++)
                    {
                        if (int(itr->first.getFile()) == int(currentFile) - 1 && itr->first.getRank() == currentRank + 1)
                        {
                            preSquare = itr->second;
                            break;
                        }
                    }
                }
                //check capture backwards left
                else if (int(it->first.getFile()) == int(currentFile) - 2 && it->first.getRank() == currentRank - 2)
                {
                    for (std::map<Location, Square*>::iterator itr = squareMap.begin(); itr != squareMap.end(); itr++)
                    {
                        if (int(itr->first.getFile()) == int(currentFile) - 1 && itr->first.getRank() == currentRank - 1)
                        {
                            preSquare = itr->second;
                            break;
                        }
                    }
                }
                
                if (it->second->getIsOccupied()
                    || (preSquare->getIsOccupied() && preSquare->getCurrentMan()->color == color)
                    || (!it->second->getIsOccupied() && !preSquare->getIsOccupied()))
                {
                    moveCandidates.erase(moveCandidates.begin() + i);
                    break; //check to be careful here
                }
            }
        }
    }

    return moveCandidates;
}

Square* Man::getCurrentSquare()
{
    return currentSquare;
}

void Man::setCurrentSquare(Square* square)
{
    this->currentSquare = square;
}

bool Man::getIsKing()
{
    return isKing;
}

void Man::setIsKing()
{
    isKing = true;
}

void Man::makeMove(Square* square)
{
    this->currentSquare->reset();
    this->currentSquare = square;
}

std::ostream& operator<<(std::ostream& ostream, const Man& man)
{
    std::string colorStr;
    switch (man.color)
    {
    case ManColor::BLACK: colorStr = "BLACK"; break;
    case ManColor::WHITE: colorStr = "WHITE"; break;
    default: colorStr = "COLOR";
    }
    return std::cout << "Man { color=" << colorStr << " } " << std::endl;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Put forward class declarations in header files and include headers in source files.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...