2014-05-09 254 views
0

我一直在努力處理頭文件和cpp文件一段時間。我認爲這與我的頭文件和cpp #include語句有關,但我不知道是什麼。我想把它弄下來,這樣我就可以進步了。我編譯和我有大約25個錯誤,看起來財產以後像這樣出現:將頭文件和.cpp文件包含到主.cpp文件中LNK2005錯誤已在對象中定義

1> Source.cpp 
1>Source.obj : error LNK2005: "public: __thiscall grid::grid(int,int)" (?? [email protected]@[email protected]@Z) already defined in grid.obj 
1>Source.obj : error LNK2005: "public: __thiscall grid::grid(int,int,int,int,int)" ([email protected]@[email protected]@Z) already defined in grid.obj 
1>Source.obj : error LNK2005: "public: __thiscall grid::grid(void)" ([email protected]@[email protected]) already defined in grid.obj 
1>Source.obj : error LNK2005: "public: void __thiscall grid::block(int,int)" ([email protected]@@[email protected]) already defined in grid.obj 
1>Source.obj : error LNK2005: "private: void __thiscall grid::checkForBlock(int,int)" ([email protected]@@[email protected]) already defined in grid.obj 
1>Source.obj : error LNK2005: "public: int __thiscall grid::column(void)const " ([email protected]@@QBEHXZ) already defined in grid.obj 
1>Source.obj : error LNK2005: "public: void __thiscall grid::display(void)const " ([email protected]@@QBEXXZ) already defined in grid.obj 
1>Source.obj : error LNK2005: "public: bool __thiscall grid::frontIsClear(void)const " ([email protected]@@QBE_NXZ) already defined in grid.obj 
1>Source.obj : error LNK2005: "public: void __thiscall grid::move(int)" ([email protected]@@[email protected]) already defined in grid.obj 
1>Source.obj : error LNK2005: "public: int __thiscall grid::nColumns(void)const " ([email protected]@@QBEHXZ) already defined in grid.obj 
1>Source.obj : error LNK2005: "public: int __thiscall grid::nRows(void)const " ([email protected]@@QBEHXZ) already defined in grid.obj 
1>Source.obj : error LNK2005: "public: void __thiscall grid::pickUp(void)" ([email protected]@@QAEXXZ) already defined in grid.obj 
1>Source.obj : error LNK2005: "public: void __thiscall grid::putDown(int,int)" ([email protected]@@[email protected]) already defined in grid.obj 
1>Source.obj : error LNK2005: "public: void __thiscall grid::putDown(void)" ([email protected]@@QAEXXZ) already defined in grid.obj 
1>Source.obj : error LNK2005: "public: bool __thiscall grid::rightIsClear(void)const " ([email protected]@@QBE_NXZ) already defined in grid.obj 
1>Source.obj : error LNK2005: "public: int __thiscall grid::row(void)const " ([email protected]@@QBEHXZ) already defined in grid.obj 
1>Source.obj : error LNK2005: "private: void __thiscall grid::setIcon(void)" ([email protected]@@AAEXXZ) already defined in grid.obj 
1>Source.obj : error LNK2005: "public: void __thiscall grid::toggleShowPath(void)" ([email protected]@@QAEXXZ) already defined in grid.obj 
1>Source.obj : error LNK2005: "public: void __thiscall grid::turnLeft(void)" ([email protected]@@QAEXXZ) already defined in grid.obj 
1>C:\Users\isaiah\C++\Letter\Debug\Letter.exe : fatal error LNK1169: one or more multiply defined symbols found 
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ========== 

繼承人的主文件(source.cpp):

#include <iostream> 
#include <string> 

using namespace std; 

#include "grid.cpp" 

int main() 
{ 

grid letter(13, 7, 3, 3, west); 
letter.move(2); 
letter.turnLeft(); 
letter.turnLeft(); 
letter.move(1); 
letter.turnLeft(); 
letter.move(8); 
letter.display(); 

system("pause"); 
return 0; 
} 

繼承人grid.h:

#ifndef GRID_H 
#define GRID_H 
const int maxRows = 22; 
const int maxCols = 36; 

/////////////////////////////////////////////////////////////////////////// 
// The grid class definition ////////////////////////////////////////////// 
/////////////////////////////////////////////////////////////////////////// 

class grid { 
public: 
    // --constructors 
    grid(); 
    // Construct a 
    grid(int totalRows, int totalCols); 
    grid(int totalRows, int totalCols, 
     int startRow, int startCol, 
     int startDirection); 

// Modifiers 
    void move(int spaces); 
    void turnLeft(); 
    void putDown(); 
    void putDown(int putDownRow, int putDownCol); 



void toggleShowPath(); 
    void pickUp(); 
    void block(int blockRow, int blockCol); 
    // pre: The intersection at (blockRow, blockCol) has nothing at all 
    //  on it, not even the mover 
    // post: The intersection at (blockRow, blockCol) is blocked. The 
    //  mover cannot move into this intersection 

// -- Accessors 
    bool frontIsClear() const; 
    bool rightIsClear() const; 
    int row() const; 
    int column() const; 
    int nRows() const; 
    int nColumns() const; 
    void display() const; 

private: 
    int lastRow;  // the number of the last row 
    int lastCol;  // the number of the last column 
    char rectangle[maxRows][maxCols]; 
    int currentRow, currentCol; // where the mover is 
    char icon;     // the symbol in the currentRow, currentCol 
    int facing;  // 0 == north, 1 == east, 2 == south, and 3 == west 
    int showPath; // whether or not the path is shown 
    void checkForBlock(int r, int c); // used by the implementation only 
    void setIcon(); // used in implementation only 
}; 

#endif // GRID_H 

...和grid.cpp(其453線長)

// File: grid.cpp 
// From: Computing Fundamentals with C++, Second Edition 
//  Rick Mercer, Franklin, Beedle, and Associates 
#include <iostream> // for endl and the objects cout, cin 
#include <cassert> // for function assert 
#include <cstdlib> // for function exit, rand() and srand() 
#include <ctime>  // for TIME 
#include <string>  // for class string 
using namespace std; 
#include "grid.h" 

// -- constuctors 

grid::grid() 
{ // Default constructor 
} 


grid::grid(int totalRows, int totalCols) 
{ // Set up a border on the edges with one escape route 
    int r, c; 

    assert(totalRows <= maxRows); 
    assert(totalRows >= 0); 
    assert(totalCols <= maxCols); 
    assert(totalCols > 0); 

    showPath = 1; // Show path when 1, when it's 0 keep the intersection visible 
    lastRow = totalRows-1; 
    lastCol = totalCols-1; 

    for(r = 0; r <= lastRow; r++) 
    for(c = 0; c <= lastCol; c++) 
     rectangle[r][c] = intersectionChar; 

    for (c = 0; c <= lastCol; c++) 
    { 
    rectangle[0][c] = blockChar;   // block first row 
    rectangle[lastRow][c] = blockChar; // blocked last row 
    } 

    for (r = 0; r <= lastRow; r++) 
    { 
    rectangle[r][0] = blockChar ;  // block first column 
    rectangle[r][lastCol] = blockChar ; // block last column 
    } 

    // Put the mover somewhere in the grid, but NOT a border 
    srand((unsigned)time(NULL));  // use the clock to randomize 
    currentRow = rand() % (lastRow-1) + 1; 
    currentCol = rand() % (lastCol-1) + 1; 

    // Pick a random direction 
    int direct(rand() % 4); 
    facing = direct; 
    setIcon(); 
    rectangle[currentRow][currentCol] = icon; 

    // Put one opening on any of the four edges 
    if(rand() % 2 == 0) 
    { // set on top or bottom at any column 
    c = rand() % lastCol; 

    if(c == 0) 
     c++;   // avoid upper and lower left corner exits (see below) 
    if(c == lastCol) 
     c--;   // avoid upper and lower right corner exits (see below) 

    if(rand() % 2 == 0) 
     r = lastRow; // half the time. on the bottom 
    else 
     r = 0;  // the other half, on the top 
    } 
    else 
    { // set on left or right at any column 
    r = rand() % lastRow; 

    if(r == 0)  // avoid upper right and left corner exits 
     r++; 
    if(r == lastRow) 
     r--;   // avoid lower left and lower right exits 

    if(rand() % 2 == 0) 
     c = lastCol; // half the time in the right column 
    else 
     c = 0;  // the other half, put on left 
    } 

    rectangle[r][c] = intersectionChar; 
} 


grid::grid(int totalRows, int totalCols, 
       int startRow, int startCol, 
       int startDirection) 
{ 
    // Check that the boundaries are okay. 
    assert(totalRows <= maxRows); 
    assert(totalRows > 0); 
    assert(totalCols <= maxCols); 
    assert(totalCols > 0); 
    // Check the initial position of the mover is within the grid 
    lastRow = totalRows-1; 
    lastCol = totalCols-1; 
    assert(startRow >= 0); 
    assert(startCol >= 0); 
    assert(startRow <= lastRow); 
    assert(startCol <= lastCol); 

    showPath = 1; // Show path when 1, when it's 0 keep the intersection visible 

    int r, c; 
    for(r = 0; r <= lastRow; r++) 
    for(c = 0; c <= lastCol; c++) 
     rectangle[r][c] = intersectionChar; 

    currentRow = startRow; 
    currentCol = startCol; 
    facing = startDirection; 
    setIcon(); 
    rectangle[currentRow][currentCol] = icon; 
} 


// -accessors 

int grid::row() const 
{ 
    return currentRow; 
} 


int grid::column() const 
{ 
    return currentCol; 
} 


int grid::nRows() const 
{ // lastRow is the number of the last row as in 0..lastRow 
    // so the total number of rows is one more than that 
    return lastRow+1; 
} 


int grid::nColumns() const 
{ // lastCol is the number of the last colukmn as in 0..lastCol 
    // so the total number of columns is one more than that 
    return lastCol+1; 
} 

bool grid::frontIsClear() const 
{ 
    switch (facing) { 
    case north : 
      if(currentRow == 0) 
      return 0; 
      else 
      if(rectangle [currentRow - 1] [currentCol] == blockChar) 
       return 0; 
      else 
       return 1; 
    case east : 
      if(currentCol == lastCol) 
      return 0; 
      else 
      if(rectangle [currentRow] [currentCol+1] == blockChar) 
       return 0; 
      else 
       return 1; 
    case south : 
      if(currentRow == lastRow) 
      return 0; 
      else 
      if(rectangle [currentRow + 1] [currentCol] == blockChar) 
       return 0; 
      else 
      return 1; 
    case west : 
     if(currentCol == 0) 
      return 0; 
     else 
      if(rectangle [currentRow] [currentCol-1] == blockChar) 
       return 0; 
      else 
      return 1; 
    } 
    return 1; 
} 

bool grid::rightIsClear() const 
{ 
    switch (facing) { 
    case west : 
      if(currentRow == 0) 
      return 0; 
      else 
      if(rectangle [currentRow - 1] [currentCol] == blockChar) 
       return 0; 
      else 
       return 1; 
    case north : 
      if(currentCol == lastCol) 
      return 0; 
      else 
      if(rectangle [currentRow] [currentCol+1] == blockChar) 
      return 0; 
      else 
      return 1; 
    case east : 
      if(currentRow == lastRow) 
      return 0; 
     else 
      if(rectangle [currentRow + 1] [currentCol] == blockChar) 
       return 0; 
      else 
      return 1; 
    case south : 
     if(currentCol == 0) 
      return 0; 
     else 
      if(rectangle [currentRow] [currentCol-1] == blockChar) 
      return 0; 
      else 
      return 1; 
    } 
    return 1; 
} 


void grid::display() const 
{ 
    int r, c; 
    cout << "The grid: " << endl; 
    for(r = 0; r <= lastRow; r++) { 
     for(c = 0; c <= lastCol; c++) 
     cout << rectangle[r][c] << ' '; 
    cout << endl; 
    } 
} 


// -modifiers 

void grid::turnLeft() 
{ 
    if(facing==north) 
     facing = west; 
    else if (facing==east) 
     facing = north; 
    else if (facing==south) 
     facing = east; 
    else if (facing==west) 
     facing = south; 
    setIcon(); 
    rectangle [currentRow] [currentCol] = icon; 
} 


void grid::setIcon() 
{ 
    if(! (rectangle [currentRow][currentCol] == thingHereChar)) { 
     switch (facing) { 
     case north : 
      icon = '^'; 
      break; 
     case east : 
      icon = '>'; 
      break; 
     case south : 
      icon = 'v'; 
      break; 
     case west : 
      icon = '<'; 
      break; 
     } 
    } 
} 


void grid::move(int spaces) 
{ 
    assert(spaces > 0); 
    int oldRow(currentRow); 
    int oldCol(currentCol); 

    switch (facing) { 
    case north : 
     currentRow-=spaces; 
     break; 
    case east : 
     currentCol+=spaces; 
     break; 
    case south : 
     currentRow+=spaces; 
     break; 
    case west : 
     currentCol-=spaces; 
     break; 
    } 
    assert (currentRow >= 0); 
    assert (currentCol >= 0); 
    assert (currentRow <= lastRow); 
    assert (currentCol <= lastCol); 

    // Fix the starting intersection 

    if(rectangle[oldRow][oldCol] == moverOnThingChar) 
    rectangle[oldRow][oldCol] = thingHereChar; 
    else if(rectangle[oldRow][oldCol] == icon && showPath) 
    rectangle[oldRow][oldCol] = beenThereChar; 
    else 
    rectangle[oldRow][oldCol] = intersectionChar; 

    int r, c; 
    switch(facing) { 
    case north: 
    for(r = oldRow; r > currentRow; r--) { 
     checkForBlock(r-1, currentCol); 
     if(rectangle[r][currentCol] != thingHereChar && showPath) 
     rectangle[r][currentCol] = beenThereChar; 
    } 
    break; 
    case east: 
    for(c = oldCol; c < currentCol; c++) { 
     checkForBlock(currentRow, c+1); 
     if(rectangle[currentRow][c] != thingHereChar && showPath) 
      rectangle[currentRow][c] = beenThereChar; 
    } 
    case south: 
    for(r = oldRow; r < currentRow; r++) { 
     checkForBlock(r+1, currentCol); 
     if(rectangle[r][currentCol] != thingHereChar && showPath) 
     rectangle[r][currentCol] = beenThereChar; 
    } 
    break; 
    case west: 
    for(c = oldCol; c > currentCol; c--) { 
     checkForBlock(currentRow, c-1); 
     if(rectangle[currentRow][c] != thingHereChar && showPath) 
     rectangle[currentRow][c] = beenThereChar; 
    } 
    } // end switch 

if(rectangle[currentRow][currentCol] == thingHereChar) 
    rectangle[currentRow][currentCol] = moverOnThingChar; 
else 
    rectangle[currentRow][currentCol] = icon; 
} 


void grid::block(int blockRow, int blockCol) 
{ 
    assert(blockRow <= lastRow); 
    assert(blockRow >= 0); 
    assert(blockCol <= lastCol); 
    assert(blockCol >= 0); 
    // Can't block the place where the mover is 
    assert(rectangle[blockRow][blockCol] != icon); 
    // Can't block the place where the an thing has been placed 
    assert(rectangle[blockRow][blockCol] != thingHereChar); 
    // Now, if everything is alright, put the block down 
    rectangle[blockRow][blockCol] = blockChar; 
} 



void grid::putDown() 
{ 
    putDown(currentRow, currentCol); 
} 

void grid::putDown(int putDownRow, int putDownCol) 
{ 
    assert(putDownRow <= lastRow); 
    assert(putDownRow >= 0); 
    assert(putDownCol <= lastCol); 
    assert(putDownCol >= 0); 
    if(rectangle[putDownRow][putDownCol] == blockChar) 
    { 
     cout << "\n**ERROR Attempt to putdown on a blocked intersection at grid(" 
      << putDownRow << ", " << putDownCol << ")" << endl << endl; 
    } 
    else 
    { 
    // First see if we need to place & for mover and object on the same intersection 
    char check = rectangle[putDownRow][putDownCol]; 
    if(check == '^' || check == '>' || check == 'v' || check == '<' || check == moverOnThingChar) 
    { 
     rectangle[putDownRow][putDownCol] = moverOnThingChar; 
    } 
    else 
     rectangle[putDownRow][putDownCol] = thingHereChar; 
    } 
} 

void grid::pickUp() 
{ 
    assert(rectangle[currentRow][currentCol] == thingHereChar || 
      rectangle[currentRow][currentCol] == moverOnThingChar); 
    // assert: Program terminated if there was nothing to pickup 
    rectangle[currentRow][currentCol] = icon; 
} 


void grid::toggleShowPath() 
{ 
    if(showPath) 
     showPath = 0; 
    else 
     showPath = 1; 
} 


void grid::checkForBlock(int r, int c) 
{ 
    if(rectangle[r][c] == blockChar) { 
    cout << endl << "Attempt to move through the block at grid(" 
         << r << ", " << c << ")" << endl; 
    if(facing == north) // must be moving north 
     rectangle[r+1][c] = icon; 
    if(facing == east) // must be moving east 
     rectangle[r][c-1] = icon; 
    if(facing == south) // must be moving south 
     rectangle[r-1][c] = icon; 
    if(facing == west) // must be moving west 
     rectangle[r][c+1] = icon; 
    for(r = 0; r < lastRow; r++) { 
     for(c = 0; c < lastCol; c++) 
      cout << rectangle[r][c] << ' '; 
     cout << endl; 
    } 
    cout << "...Program terminating..." << endl; 
    exit(0); 
    } 
} 
+1

你可能需要更改標籤的CPP問題 – Plutonix

+0

哈哈哎呀良好的通話。 – 0000

回答

1

編譯.cpp文件時,C++編譯器將首先運行預處理器並生成編譯單元。編譯單元將由源文件組成,其中所有#include指令均由它們引用的文件的內容替換。

在您的代碼中,Source.cpp文件包含grid.cpp。結果是grid.cpp的全部內容將在編譯單元中內聯。

鏈接器將嘗試鏈接生成的Source.objgrid.obj文件,但它們都將包含grid.cpp文件中方法的定義。這是編譯器告訴你的。

解決方法是用#include "grid.h"替換#include "grid.cpp"行。

編輯

爲了在grid.cpp可供source.cpp頂部定義的常量,而不包括grid.cpp則需要使用extern關鍵字來聲明他們grid.h

extern const char intersectionChar; 
extern const char beenThereChar; 
extern const char blockChar; 
extern const char thingHereChar; 
extern const char moverOnThingChar; 
extern const int north; 
extern const int east; 
extern const int south; 
extern const int west; 

extern關鍵字告訴編譯器指出變量是在另一個編譯單元中定義的,並且它們的地址/值將在鏈接時解析。

EDIT

步驟1:將以下各行以grid.h頂部:

extern const char intersectionChar; 
extern const char beenThereChar; 
extern const char blockChar; 
extern const char thingHereChar; 
extern const char moverOnThingChar; 
extern const int north; 
extern const int east; 
extern const int south; 
extern const int west; 

步驟2:將以下行的grid.cpp頂部:

const char intersectionChar = '.'; 
const char beenThereChar = ' '; 
const char blockChar = '#'; 
const char thingHereChar = 'O'; 
const char moverOnThingChar = '&'; 
const int north = 0; 
const int east = 1; 
const int south = 2; 
const int west = 3; 

有了這些改變,所有的東西都使用g ++ 4.8.2編譯。

+0

不幸的是,我已經嘗試過,這是在source.cpp中它說:grid(13,7,3,3,west);它聲稱,在.cpp文件中明確定義的時候,west是未定義的。 – 0000

+0

'extern'的定義應該放在頭文件中。這意味着編譯器將強制一個單元中的非外部定義與另一個單元試圖訪問的內容相匹配。 –

+0

@ musicman_385,'west'沒有在'source.cpp'中定義。 'source.cpp'應該包含'grid.h','grid.h'應該在TAS的答案中列出'extern'的定義。 –

1

在文件源中。CPP,改變這種:

#include "grid.cpp" 

要這樣:

#include "grid.h"