使用Extern的链接器问题

时间:2012-11-28 22:03:49

标签: c++ linker

所以我有两场比赛并排进行。

proj2/main.cpp (main that gets run that then can call either game)
proj2/spades/display.cpp
proj2/spades/gameplay.cpp
proj2/spades/otherFiles.cpp
proj2/hearts/display.cpp (this is the same display class as in the spades game with the same functions just sightly altered.)
proj2/hearts/hearts.cpp
proj2/hearts/otherFiles.cpp

我收到以下链接器错误,

./gamePlay.o: In function `__static_initialization_and_destruction_0(int, int)':
gamePlay.cpp:(.text+0x396): undefined reference to `spades::display::display()'
./gamePlay.o: In function `__tcf_3':
gamePlay.cpp:(.text+0x480): undefined reference to `spades::display::~display()'

在我的gamePlay.cpp文件中我定义了以下内容,我认为这是我的错误所在,

 display monitor;

如果我将extern标识符添加到行中,例如

extern display monitor;

错误将仅消失以产生以下问题,

./gamePlay.o: In function `spades::gamePlay::storeBid(std::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >&)':
    gamePlay.cpp:(.text+0x14ee): undefined reference to `spades::monitor'
    gamePlay.cpp:(.text+0x14f3): undefined reference to `spades::display::drawBox(int, int, int, int, int)'

我认为这个错误来自以下几行,但我不知道如何修复此错误。此刻感觉很丢失。 (我不明白为什么我需要extern作为监视器的标识符)。所有的包括都应该没问题。

int key = monitor.captureInput();
         monitor.drawBox(2, 5, 3, 2, 0);

下面是我的display.h文件

/*
 * Description: Defines constants and class prototypes and variables
 */

// These are include files they are used for accessing functions and
// variables in external libraries.
#include <ncursesw/ncurses.h>
#include <iostream>
#include <cstdio>
// This is the namespace std, without this you would need to add "std::"
// infront of every variable and function from the std library.
//using namespace std;

// These Mouse Mask Definitions are for some of the common mouse buttons
// that are used in this project.
#define LEFT_UP    1
#define LEFT_DOWN  2
#define LEFT_CLICK 4
#define LEFT_DOUBLECLICK 24

#define RIGHT_UP    4096
#define RIGHT_DOWN  8192
#define RIGHT_CLICK 16384
#define RIGHT_DOUBLECLICK 32768

#define MIDDLE_ROLLUP    1048576
#define MIDDLE_ROLLDOWN  256
namespace spades {
// Some extended character definitions for showing the special symbols
// in the extended UTF-8 character map.
const char joker[]    = {0xE2, 0x98, 0xBA, 0};
const char clubs[]    = {0xE2, 0x99, 0xA3, 0};
const char diamonds[] = {0xE2, 0x99, 0xA6, 0};
const char hearts[]   = {0xE2, 0x99, 0xA5, 0};
const char spades[]   = {0xE2, 0x99, 0xA0, 0};

/*
 * This is the display class definitions
 */
class display {
public:
    /* "constructor"
    * This function is called whenever a new object of class display is first
    * created. Put initialization functions in here.
    */
    display(void){};
    /* "destructor"
    * This function is called just before a object is deleted. Put clean up
    * functions in here.
    */
    ~display(){}; // destructor

    // captures user input
    int captureInput(void);
    // stores new screensize on update
    void handleResize(int sig);

    /*
     * Drawing commands
     */
    // display a card on the screen
    void displayCard(int x, int y, int suit, int number, int printAtt);
    // erase in the shape of a box on the screen
    void eraseBox(int x, int y, int sizeX, int sizeY);
    // draw a box on the screen
    void drawBox(int x, int y, int sizeX, int sizeY, int printAtt);
    // display banner text at the bottom of the screen
    void bannerBottom(std::string bannerText);
    void bannerAboveBottom(std::string bannerText);
    // display banner text at the top of the screen
    void bannerTop(std::string bannerText);

    // get information about the display
    int getCols(void) {return cols;}
    int getLines(void) {return lines;}
    int getMouseEventX(void) {return mouseEventX;}
    int getMouseEventY(void) {return mouseEventY;}
    int getMouseEventButton(void) {return mouseEventButton;}

    // Updates the screen after you finish drawing
    void updateScreen(void) {refresh();}

    // sets an offset for when cards clip the bottom of the screen
    void setBottomOffset(int offset) {lineBoundaryOffset=offset;}

private:
    // These are private functions and variables used inside of display.
    // You should not try to access these from outside the display class.
    void printFace(int suit, int number, int line, int printAtt);
    void printSuit(int suit);
    void printNumber(int number);

    int cols;
    int lines;
    int mouseEventX;
    int mouseEventY;
    int mouseEventButton;
    int lineBoundaryOffset;
};
}

以下是我的display.cpp文件

/* 
 * Description: Defines the functionality of the user interface.
 *
 * NOTES:
 *      * Requires the terminal (Putty) to be set to UTF-8.
 *      * Does not function when running a screen session.
 */
#include <iostream>
#include <sys/ioctl.h>
#include <cstdio>
#include <unistd.h>
#include <locale.h>
#include <ncursesw/ncurses.h>

#include "display.h"
namespace spades {
//using namespace std;

/* Function: This is the constructor.
 * Description: It is called whenever an object of class display is initialized
 */
display::display(void) {
    /* Initilization of Terminal */
    // required to get card suits displaying, combined with UTF-8 set in terminal
    setlocale(LC_ALL,"en_US.utf-8");

    // initialize ncurses screen
    initscr();
    // allow for color settings
    start_color();
    // clear the screen
    clear();
    // turn off the keyboard echo (reqiured while drawing)
    noecho();
    // Change to character mode (so individual characters are being read at a
    // time rather than waiting for a carriage return).
    cbreak();
    // Allows for function keys to be used (also nessacary for getting the mouse
    // movement working).
    keypad(stdscr, TRUE);
    // set which mouse events are captured
    mousemask(ALL_MOUSE_EVENTS, NULL);
    // Setting the timeout for the capture input values are in 1/10ths of a second.
    halfdelay(5);

    // setup the screen size settings.
    cols = 80;
    lines = 24;
    // this updates the locally stored col and line variables
    handleResize(0);
    // set a no card draw offset of 1 so the bottom banner is not overwritten
    lineBoundaryOffset = 1;

    // Settings for card colors (these can be set outside of the display class)
    init_pair(1, COLOR_CYAN, COLOR_BLACK); // for card outline
    init_pair(2, COLOR_BLUE, COLOR_BLACK); // for spades and clubs
    init_pair(3, COLOR_RED, COLOR_BLACK);  // for hearts and diamonds
    init_pair(4, COLOR_GREEN, COLOR_BLACK); // for turned over card
    init_pair(5, COLOR_GREEN, COLOR_BLACK); // for box drawing
    init_pair(6, COLOR_GREEN, COLOR_BLACK); // for banner display
}

/* Function: This is the destructor.
 * Description: This is called just before an object is deleted.
 */
display::~display() {
    // this is turns off all the special settings and returns the terminal to normal
    endwin();
    // insert deletion of dynamically created objects here too
}

/*
 * Function: This captures all the userinput.
 * Description: It captures mouse and keyboard events.
 *      Returns "Positive Number"
 *          - for user keypress
 *          - this is a character code typed
 *      Returns "0" - for no user input
 *          - this is when nothing is typed for half a second
 *          - allows for other timed operations to occur
 *      Returns "-1" - for mouse event
 *          - details of the mouse event must be fetched from this class
 *          - use getMouseEventX, getMouseEventY and getMouseEventButton
 */
int display::captureInput(void) {
    // obtain one mouse event or keypress
    int ch=getch();
    // this is a switch statement for the result of getch
    switch (ch) {
    case KEY_MOUSE: // this occurs when an mouse event occurs
      {
        MEVENT mevent; // this is a variable declared of type MEVENT
        getmouse(&mevent); // this gets the mouse event from ncurses (library)
        mouseEventX = mevent.x; // get the column location of the event
        mouseEventY = mevent.y; // get the row location of the event
        mouseEventButton = mevent.bstate; // get the button state of the mouse
        return -1; // -1 is for a mouse event
      }
      break;
    case ERR: // this occurs when there is a timeout
      {
        return 0; // 0 is when nothing occurs
      }
      break;
    default: // this occurs when a key is pressed
      return ch; // a character is when the user types something
    }

    return 0; // this is never called, but is used to stop compiler complaints
}

/*
 * Function: Updates all the information in the display class on window resize
 * Description: This function just updates information, it requires the call
 *      from a static singal handler. Signal handlers service interrupts and require
 *      a static function to be called, because they are not part of the main
 *      program control flow. The signal handler should be declared in the main
 *      class, because your game should redraw the display on a resize.
 */
void display::handleResize(int sig) {
#ifdef TIOCGSIZE // operating system dependant differences
    struct ttysize ts;
    ioctl(STDIN_FILENO, TIOCGSIZE, &ts); // get the information of the terminal
    cols = ts.ts_cols;
    lines = ts.ts_lines;
#elif defined(TIOCGWINSZ)
    struct winsize ts;
    ioctl(STDIN_FILENO, TIOCGWINSZ, &ts); // get the information of the terminal
    cols = ts.ws_col;
    lines = ts.ws_row;
#endif /* TIOCGSIZE */
    resizeterm(lines, cols); // sets the ncurses window size correctly
}

/*
 * Function: Displays various cards on the game screen
 * Description: This function displays various playing cards on the screen.
 *      The first two arguments are the x and y coordinates of the top left corner
 *      of the card.
 *          The suit values are: 1=spades, 2=hearts, 3=clubs, 4=diamonds
 *          The numbers are: 1=Ace, 2-10=2-10, 11=Jack, 12=Queen, 13=King, 14=Joker
 *      Any suit and number that do not match the valid numberrs generates a face down
 *      card.
 *          The printAtt allows for one or more any of the following display settings:
 *              A_NORMAL        Normal display (no highlight)
 *              A_STANDOUT      Best highlighting mode of the terminal.
 *              A_UNDERLINE     Underlining
 *              A_REVERSE       Reverse video
 *              A_BLINK         Blinking
 *              A_DIM           Half bright
 *              A_BOLD          Extra bright or bold
 *              A_PROTECT       Protected mode
 *              A_INVIS         Invisible or blank mode
 *              A_ALTCHARSET    Alternate character set
 *              A_CHARTEXT      Bit-mask to extract a character
 *              COLOR_PAIR(n)   Color-pair number n
 */
void display::displayCard(int x, int y, int suit, int number, int printAtt) {

    // Ncurses drawing settings
    attron(COLOR_PAIR(1) | printAtt);
    // prevent draw if it off the screen
    if (x>=0 && y>=0 && x<cols-6 && y<lines-lineBoundaryOffset) {
        // print the top lines of the card
        mvprintw(y,x,"\u250c\u2500\u2500\u2500\u2500\u2510");
        // the next 4 if statements prevent draw if it is over the bottom of the screen
        if (y<lines-1-lineBoundaryOffset) {
            move(y+1,x); // move command
            printFace(suit,number,0, printAtt); // call function to print card face
        }
        if (y<lines-2-lineBoundaryOffset) {
            move(y+2,x); // move command
            printFace(suit,number,1, printAtt); // call function to print card face
        }
        if (y<lines-3-lineBoundaryOffset) {
            move(y+3,x); // move command
            printFace(suit,number,2, printAtt); // call function to print card face
        }
        if (y<lines-4-lineBoundaryOffset) {
            // prints the bottom lines of the card
            mvprintw(y+4,x,"\u2514\u2500\u2500\u2500\u2500\u2518");
        }
    }
    // Ncurses turn off the drawing settings
    attroff(COLOR_PAIR(1) | printAtt);
}

/*
 * Function: Print a single line of what is written on the card.
 * Description: This copies suit, number and printAtt from the calling function.
 *      Also includes what line of the card face is being drawn.
 */
void display::printFace(int suit, int number, int line, int printAtt) {
    // draw left edge of the card
    printw("\u2502");

    if (suit==2 || suit==4) { // Red for Hearts and Diamonds
        attron(COLOR_PAIR(3) | printAtt);
    } else { // Black for Spades and Clover
        attron(COLOR_PAIR(2) | printAtt);
    }

    // this the display of the joker
    if (number==14) {
        if (line==0)
            printw("J%s  ", joker);
        if (line==1)
            printw("oker");
        if (line==2)
            printw("  J%s", joker);
    // this is the display for the cards with suits and numbers
    } else if (suit>=1 && suit <=4 && number>=1 && number<=13) {
        if (line==0) {
            printSuit(suit); // function to draw suit
            printNumber(number); // function to draw number
            if (number!=10)
                printw(" ");
            printw(" ");
        } else if (line==2) {
            if (number!=10)
                printw(" ");
            printw(" ");
            printNumber(number); // function to draw number
            printSuit(suit);    // function to draw suit
        } else {
            printw("    ");
        }
    // this is for a face down card
    } else {
        // the face down cards have a special color
        attron(COLOR_PAIR(4) | printAtt);
        if (line==0)
            printw("%s  %s", spades, hearts);
        if (line==1)
            printw("Play");
        if (line==2)
            printw("%s  %s", diamonds, clubs);
        attroff(COLOR_PAIR(1) | printAtt);
    }

    // turn on the card edge color settings
    attron(COLOR_PAIR(1) | printAtt);
    // print the right edge of the card
    printw("\u2502");
}

/*
 * Function: Print the suit of the card
 * Description: This is just a look up table.
 */
void display::printSuit(int suit) {
    switch (suit) {
        case 1:
            printw("%s",spades);
            break;
        case 2:
            printw("%s",hearts);
            break;
        case 3:
            printw("%s",clubs);
            break;
        case 4:
            printw("%s",diamonds);
            break;
        default:
            printw(" ");
            break;
    }
}

/*
 * Function: Prints the number on the card
 * Description: This is just a look up table.
 */
void display::printNumber(int number) {
    switch (number) {
        case 2:
        case 3:
        case 4:
        case 5:
        case 6:
        case 7:
        case 8:
        case 9:
        case 10:
            printw("%i",number);
            break;
        case 1:
            printw("%c",'A');
            break;
        case 11:
            printw("%c",'J');
            break;
        case 12:
            printw("%c",'Q');
            break;
        case 13:
            printw("%c",'K');
            break;
        default:
            printw(" ");
            break;
    }
}

/*
 * Function: Erases a rectangle on the screen
 * Description: x,y is for the top left corner, sizeX and sizeY set
 *          how big the square is.
 */
void display::eraseBox(int x, int y, int sizeX, int sizeY) {
    std::string strDraw;
    int yCount;
    int maxSizeX;

    // this limits the column size of the draw when it is over the edge
    // of the drawing area
    if (sizeX+x > cols)
        maxSizeX=cols-x;
    else
        maxSizeX=sizeX;

    // for the number of rows that need to be drawn
    for (yCount=0; yCount<sizeY;yCount++) {
        // if the box goes over the edge of the drawable screen
        // stop drawing by breaking the loop
        if (yCount+y > lines-lineBoundaryOffset || y < 0)
            break;
        // reset the line to be drawn
        strDraw = "";
        // check that x is not off the screen
        if (x<=cols && x >= 0) {
            // make a string needed for box width
            strDraw.append(maxSizeX,' ');
            // print the line of the box
            mvprintw(y+yCount,x,"%s",strDraw.c_str());
        }
    }
}

/*
 * Function: Draws a box on the screen
 * Description: x,y is for the top left corner, sizeX and sizeY set
 *          how big the square is. printAtt allows for changes in the
 *          display settings.
 */
void display::drawBox(int x, int y, int sizeX, int sizeY, int printAtt) {
    std::string strDraw;
    int ii;
    int yCount;

    // set the box setting colors on
    attron(COLOR_PAIR(5) | printAtt);

    // for the box height being drawn loop
    for (yCount=0; yCount<sizeY;yCount++) {
        // break loop if the drawing is offscreen
        if (yCount+y > lines-lineBoundaryOffset || y < 0)
            break;
        // if x is on the screen
        if (x<=cols) {
            strDraw = "";
            // for the box width loop
            for (ii=0;ii<sizeX;ii++){
                // stop drawing if the x is offscreen
                if (ii+x > cols || x < 0)
                    break;
                // first line
                if (yCount==0) {
                    if (ii==0) {
                        strDraw.append("\u250c"); // left
                    } else if (ii==sizeX-1) {
                        strDraw.append("\u2510"); // right
                    } else {
                        strDraw.append("\u2500"); // middle
                    }
                // last line
                } else if (yCount==sizeY-1) {
                    if (ii==0) {
                        strDraw.append("\u2514"); // left
                    } else if (ii==sizeX-1) {
                        strDraw.append("\u2518"); // right
                    } else {
                        strDraw.append("\u2500"); // middle
                    }
                // other lines
                } else {
                    if (ii==0) {
                        strDraw.append("\u2502"); // left
                    } else if (ii==sizeX-1) {
                        strDraw.append("\u2502"); // right
                    } else {
                        strDraw.append(" "); // middle
                    }
                }
            }
            // print the line that was created
            mvprintw(y+yCount,x,"%s",strDraw.c_str());
        }
    }
    // turn off the attribute colors
    attroff(COLOR_PAIR(5) | printAtt);
}

/*
 * Function: Draws a banner of text at the bottom right of the screen
 * Description: Inverts the color and draws the banner at the bottom
 *      of the screen. Does not handle carriage returns on the string.
 */
void display::bannerBottom(std::string bannerText) {
    // change to the banner draw settings
    attron(COLOR_PAIR(6) | A_REVERSE | A_BOLD);
    // checks if the banner string size is smaller than the width of the screen
    if((unsigned)cols > bannerText.size()) {
        // moves the cursor to the bottom of the screen
        move(lines-1,0);
        // fill in extra space to the banner text is right adjusted
        hline(' ',cols - bannerText.size());
        // prints out the banner text
        mvprintw(lines-1,cols-bannerText.size(),"%s", bannerText.c_str());
    // if banner string size is larger than width of screen
    } else {
        // clip the banner text so it doesn't wrap over to the next line
        mvprintw(lines-1,0,"%s", (bannerText.substr(0,cols)).c_str());
    }
    // turn off the draw colors
    attroff(COLOR_PAIR(6) | A_REVERSE | A_BOLD);
}

void display::bannerAboveBottom(std::string bannerText) {
    // change to the banner draw settings
    attron(COLOR_PAIR(1) | A_REVERSE | A_BOLD);
    // checks if the banner string size is smaller than the width of the screen
    if((unsigned)cols > bannerText.size()) {
        // moves the cursor to the bottom of the screen
        move(lines-2,0);
        // fill in extra space to the banner text is right adjusted
        hline(' ',cols - bannerText.size());
        // prints out the banner text
        mvprintw(lines-2,cols-bannerText.size(),"%s", bannerText.c_str());
    // if banner string size is larger than width of screen
    } else {
        // clip the banner text so it doesn't wrap over to the next line
        mvprintw(lines-2,0,"%s", (bannerText.substr(0,cols)).c_str());
    }
    // turn off the draw colors
    attroff(COLOR_PAIR(1) | A_REVERSE | A_BOLD);
}

/*
 * Function: Draws a banner of text at the top left of the screen
 * Description: Inverts the color and draws the banner at the top
 *      of the screen. Does not handle carriage returns on the string.
 */
void display::bannerTop(std::string bannerText) {
    // change to the banner draw settings
    attron(COLOR_PAIR(6) | A_REVERSE | A_BOLD);
    // checks if the banner string size is smaller than the width of the screen
    if((unsigned)cols > bannerText.size()) {
        // moves the cursor to the bottom of the screen
        move(0,0);
        // prints out the banner text
        printw("%s", bannerText.c_str());
        // fill in extra space after the banner text
        hline(' ',cols - bannerText.size());
    // if banner string size is larger than width of screen
    } else {
        // clip the banner text so it doesn't wrap over to the next line
        mvprintw(0,0,"%s", (bannerText.substr(0,cols)).c_str());
    }
    // turn off the draw colors
    attroff(COLOR_PAIR(6) | A_REVERSE | A_BOLD);
}
}

以下是我的gameplay.h文件

#include "player.h"
#include "display.h"

#ifndef gamePlay_H
#define gamePlay_H
namespace spades {

class gamePlay{

    bool spadesBroken;

public:
    vector <spades::card> getDeck();
    vector <spades::player>getplayers();
    bool getSpadesBroken() {return spadesBroken;}
    void setSpadesBroken(bool b){spadesBroken = b;}

    int compareCenter(int leadplayer);
    void createDeck();
    void deal(vector <spades::card> &deck, vector <spades::player> &players);
    void handSort();
    bool containSuit(spades::card lead, spades::player players);
    bool onlySpade(spades::player play);

    int handCheck(int xevent, int yevent, vector <spades::player> players, int trickStart);

    void displayHand();
    void displayAdd();
    void humanPlay(int trickStart);
    void CPUplay(int trickStart, int CPU);
    void score(spades::player &play, spades::player &play2);
    void storeBid(stringstream &msg);
    void runGame();

};
}
#endif

以下是我的gameplay.cpp文件

#include <iostream>
#include <sys/ioctl.h>
#include <cstdio>
#include <unistd.h>
#include <locale.h>
#include <ncursesw/ncurses.h>
#include <fstream>


#include "gamePlay.h"
#include <cstdlib>
#include <sstream>
#include <ctime>
namespace spades {
vector <spades::player> players(4);
vector <spades::card> deck(52);
display monitor;
card center[4];

vector <spades::card> gamePlay::getDeck(){return deck;}
vector <spades::player> gamePlay::getplayers(){return players;}

//sorts the cards in the players hand into diamonds, clubs, hearts, spades
void gamePlay::handSort(){
    int spades[13];
    int hearts[13];
    int clubs[13];
    int diamonds[13];
    int index;
    int i;
    for(i=0; i<13; i++){ //determines the card number and places them into corresponding indexes
        index = (players.at(0).hand.at(i).getCardNum()+11)%13; //cause the cards to be placed based on their number with 2 being index 0 and 1(ace) being index 12
        switch(players.at(0).hand.at(i).getSuit())
        {
        case 1: spades[index] = 1;
        break;
        case 2: hearts[index] = 1;
        break;
        case 3: clubs[index] = 1;
        break;
        case 4: diamonds[index] = 1;
        break;
        default: mvprintw(3,2,"!!!!!!!we have a problem!!!!!!!!!!");
        break;
        }
    }
    i = 0;
    while(i<13){ //being placing the ordered cards back into the players hand
        int j = 0;
        while(j < 13){
            if(diamonds[j] == 1){ //if a card has been placed in this index for the diamonds only array
                if(j+2 == 14) //if the card is an ace
                    players.at(0).hand.at(i).setCardNum(1);
                else
                    players.at(0).hand.at(i).setCardNum(j+2); //add 2 to each index to get the card number
                players.at(0).hand.at(i).setSuit(4);
                i++;
            }
            j++;
        }
        j = 0;
        while(j < 13){
            if(clubs[j] == 1){
                if(j+2 == 14)
                    players.at(0).hand.at(i).setCardNum(1);
                else
                    players.at(0).hand.at(i).setCardNum(j+2);
                players.at(0).hand.at(i).setSuit(3);
                i++;
            }
            j++;
        }
        j = 0;
        while(j < 13){
            if(hearts[j] == 1){
                if(j+2 == 14)
                    players.at(0).hand.at(i).setCardNum(1);
                else
                    players.at(0).hand.at(i).setCardNum(j+2);
                players.at(0).hand.at(i).setSuit(2);
                i++;
            }
            j++;
        }
        j = 0;
        while(j < 13){
            if(spades[j] == 1){
                if(j+2 == 14)
                    players.at(0).hand.at(i).setCardNum(1);
                else
                    players.at(0).hand.at(i).setCardNum(j+2);
                players.at(0).hand.at(i).setSuit(1);
                i++;
            }
            j++;
        }
    }
}

//compares the center pile of 4 played cards to determine who wins the trick
int gamePlay::compareCenter(int leadplayer){
    int highest = center[leadplayer].getCardNum();
    if(center[leadplayer].getCardNum() == 1)
        highest = 14;
    int suit = center[leadplayer].getSuit();
    int player = leadplayer;

    for(int i = leadplayer+1; i < leadplayer+4; i++)
    {
        if(center[i%4].getSuit() == 1)
            setSpadesBroken(true);
        if((suit != 1) && (center[i%4].getSuit() == 1))
        {
            player = i%4;
            suit = 1;
            highest = center[i%4].getCardNum();
        }
        if(suit == center[i%4].getSuit()){
            if(center[i%4].getCardNum() == 1){
                player = i % 4;
                highest = 14;
            }
            if(highest < center[i%4].getCardNum())
            {
                player = i%4;
                highest = center[i%4].getCardNum();
            }
        }
    }
    players.at(player).setTricksTaken(players.at(player).getTricksTaken()+1); //increments the trick count of the winning player
    return player; //return the player who won to determine who goes first next turn
}

//Create the deck of 52 cards by setting the suit and number of each card to a nonzero integer
void gamePlay::createDeck() {
    for(int j = 0; j < 52; j++)
    {
        deck.at(j).setCardNum((j%13)+1);
        deck.at(j).setSuit((j/13)+1);
    }
    random_shuffle(deck.begin(), deck.end());
}

//deal out 13 cards to each player by setting the
void gamePlay::deal(vector <spades::card> &newdeck, vector <spades::player> &newplayers){
    for(int i = 0; i<52; i++){
        newplayers.at(i/13).addCard(newdeck.at(i));
        newdeck.at(i).setSuit(0);
        newdeck.at(i).setCardNum(0);
    }
}

//determines if the player still has a card of the same suit in their hand as the leading card played
bool gamePlay::containSuit(spades::card lead, spades::player players){
    bool suit = false;
    for(int i = 0; i < players.getHand().size(); i++){
        if(lead.getSuit() == players.getHand().at(i).get

2 个答案:

答案 0 :(得分:0)

你必须像这样编写默认的构造函数和析构函数:

struct display
{
    display()  { }
    ~display() { }
    //        ^^^^
};

而不是这样:

struct display
{
    display();
    ~display();
};

但是,如果您在标题中确实有后一种形式并希望保持这种形式,则需要在源文件中添加定义:

display::display() { }
display::~display() { }

答案 1 :(得分:0)

链接器抱怨找不到对象spades::monitor和函数spades::display::drawBox(int, int, int, int)。这些定义在哪里?请注意,在.cpp文件(或其类定义之外的任何位置)中定义成员变量/成员函数时,必须使用类名限定它。例如:

在.h

namespace spades {

class display {

  static display monitor;

  void drawBox(int, int, int, int);
};

}

在.cpp

namespace spades {

display display::monitor;

void display::drawBox(int, int, int, int) {
  //...
}

}

如果没有看到完整的代码(至少是链接器所抱怨的东西的定义),很难说更多。