我一直在努力处理头文件和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);
}
}
答案 0 :(得分:1)
编译.cpp文件时,c ++编译器将首先运行预处理器并生成编译单元。编译单元将包含源文件,所有#include
指令都被它们引用的文件的内容替换。
在您的代码中,Source.cpp
文件包含grid.cpp
。结果是grid.cpp
的全部内容将在编译单元中内联。
然后,链接器将尝试链接生成的Source.obj
和grid.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"