包括头和.cpp文件到主.cpp文件LNK2005错误已在对象中定义

时间:2014-05-09 17:43:46

标签: c++ visual-studio-2012

我一直在努力处理头文件和cpp文件。我认为这与我的标题和cpp #include语句有关,但我不知道是什么。我想把它搞定,这样我才能进步。我编译,我想出了大约25个看起来像这样的错误:

1>  Source.cpp
1>Source.obj : error LNK2005: "public: __thiscall grid::grid(int,int)" (?? 0grid@@QAE@HH@Z) already defined in grid.obj
1>Source.obj : error LNK2005: "public: __thiscall grid::grid(int,int,int,int,int)" (??0grid@@QAE@HHHHH@Z) already defined in grid.obj
1>Source.obj : error LNK2005: "public: __thiscall grid::grid(void)" (??0grid@@QAE@XZ) already defined in grid.obj
1>Source.obj : error LNK2005: "public: void __thiscall grid::block(int,int)" (?block@grid@@QAEXHH@Z) already defined in grid.obj
1>Source.obj : error LNK2005: "private: void __thiscall grid::checkForBlock(int,int)" (?checkForBlock@grid@@AAEXHH@Z) already defined in grid.obj
1>Source.obj : error LNK2005: "public: int __thiscall grid::column(void)const " (?column@grid@@QBEHXZ) already defined in grid.obj
1>Source.obj : error LNK2005: "public: void __thiscall grid::display(void)const " (?display@grid@@QBEXXZ) already defined in grid.obj
1>Source.obj : error LNK2005: "public: bool __thiscall grid::frontIsClear(void)const " (?frontIsClear@grid@@QBE_NXZ) already defined in grid.obj
1>Source.obj : error LNK2005: "public: void __thiscall grid::move(int)" (?move@grid@@QAEXH@Z) already defined in grid.obj
1>Source.obj : error LNK2005: "public: int __thiscall grid::nColumns(void)const " (?nColumns@grid@@QBEHXZ) already defined in grid.obj
1>Source.obj : error LNK2005: "public: int __thiscall grid::nRows(void)const " (?nRows@grid@@QBEHXZ) already defined in grid.obj
1>Source.obj : error LNK2005: "public: void __thiscall grid::pickUp(void)" (?pickUp@grid@@QAEXXZ) already defined in grid.obj
1>Source.obj : error LNK2005: "public: void __thiscall grid::putDown(int,int)" (?putDown@grid@@QAEXHH@Z) already defined in grid.obj
1>Source.obj : error LNK2005: "public: void __thiscall grid::putDown(void)" (?putDown@grid@@QAEXXZ) already defined in grid.obj
1>Source.obj : error LNK2005: "public: bool __thiscall grid::rightIsClear(void)const " (?rightIsClear@grid@@QBE_NXZ) already defined in grid.obj
1>Source.obj : error LNK2005: "public: int __thiscall grid::row(void)const " (?row@grid@@QBEHXZ) already defined in grid.obj
1>Source.obj : error LNK2005: "private: void __thiscall grid::setIcon(void)" (?setIcon@grid@@AAEXXZ) already defined in grid.obj
1>Source.obj : error LNK2005: "public: void __thiscall grid::toggleShowPath(void)" (?toggleShowPath@grid@@QAEXXZ) already defined in grid.obj
1>Source.obj : error LNK2005: "public: void __thiscall grid::turnLeft(void)" (?turnLeft@grid@@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;
}

heres 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);
  }
}

2 个答案:

答案 0 :(得分:1)

编译.cpp文件时,c ++编译器将首先运行预处理器并生成编译单元。编译单元将包含源文件,所有#include指令都被它们引用的文件的内容替换。

在您的代码中,Source.cpp文件包含grid.cpp。结果是grid.cpp的全部内容将在编译单元中内联。

然后,链接器将尝试链接生成的Source.objgrid.obj文件,但它们都将包含grid.cpp文件中方法的定义。这就是编译器告诉你的。

解决方案是将行#include "grid.cpp"替换为#include "grid.h"

修改

要使grid.cpp的{​​{1}}顶部定义的常量不包括source.cpp,您需要使用grid.cpp关键字在grid.h中声明它们:

extern

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; 关键字告诉编译器变量是在另一个编译单元中定义的,并且它们的地址/值将在链接时解析。

修改

第1步:在extern

的顶部插入以下行
grid.h

第2步:在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;

的顶部插入以下行
grid.cpp

使用这些更改,所有内容都可以使用g ++ 4.8.2进行编译。

答案 1 :(得分:1)

在文件source.cpp中,更改此:

#include "grid.cpp"

对此:

#include "grid.h"