当我尝试编译并且不知道为什么
时,我一直收到此错误Ld /Users/Itunes/Library/Developer/Xcode/DerivedData/BATTLESHIP-gefqfgwzntvzlvfyyxoqzmmanjlb/Build/Products/Debug/BATTLESHIP normal x86_64
cd /Users/Itunes/Desktop/Programs/CMPSC122/BATTLESHIP
setenv MACOSX_DEPLOYMENT_TARGET 10.7
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++ -arch x86_64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk -L/Users/Itunes/Library/Developer/Xcode/DerivedData/BATTLESHIP-gefqfgwzntvzlvfyyxoqzmmanjlb/Build/Products/Debug -F/Users/Itunes/Library/Developer/Xcode/DerivedData/BATTLESHIP-gefqfgwzntvzlvfyyxoqzmmanjlb/Build/Products/Debug -filelist /Users/Itunes/Library/Developer/Xcode/DerivedData/BATTLESHIP-gefqfgwzntvzlvfyyxoqzmmanjlb/Build/Intermediates/BATTLESHIP.build/Debug/BATTLESHIP.build/Objects-normal/x86_64/BATTLESHIP.LinkFileList -mmacosx-version-min=10.7 -stdlib=libc++ -o /Users/Itunes/Library/Developer/Xcode/DerivedData/BATTLESHIP-gefqfgwzntvzlvfyyxoqzmmanjlb/Build/Products/Debug/BATTLESHIP
duplicate symbol __ZlsRNSt3__113basic_ostreamIcNS_11char_traitsIcEEEERK5Point in:
/Users/Itunes/Library/Developer/Xcode/DerivedData/BATTLESHIP-gefqfgwzntvzlvfyyxoqzmmanjlb/Build/Intermediates/BATTLESHIP.build/Debug/BATTLESHIP.build/Objects-normal/x86_64/main.o
/Users/Itunes/Library/Developer/Xcode/DerivedData/BATTLESHIP-gefqfgwzntvzlvfyyxoqzmmanjlb/Build/Intermediates/BATTLESHIP.build/Debug/BATTLESHIP.build/Objects-normal/x86_64/Board.o
duplicate symbol __ZlsRNSt3__113basic_ostreamIcNS_11char_traitsIcEEEERK5Point in:
/Users/Itunes/Library/Developer/Xcode/DerivedData/BATTLESHIP-gefqfgwzntvzlvfyyxoqzmmanjlb/Build/Intermediates/BATTLESHIP.build/Debug/BATTLESHIP.build/Objects-normal/x86_64/main.o
/Users/Itunes/Library/Developer/Xcode/DerivedData/BATTLESHIP-gefqfgwzntvzlvfyyxoqzmmanjlb/Build/Intermediates/BATTLESHIP.build/Debug/BATTLESHIP.build/Objects-normal/x86_64/Ship.o
ld: 2 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
我的标题和.cpp文件是
Board.h
// Board.h - Board class declaration
#pragma once
#include "Point.h"
using namespace std;
#define HIT 'X'
#define SHIP 'S'
#define MISS 'O'
#define WATER '~'
class Board
{
public:
// Constructor
Board();
// Function which prints an image of the board showing hits ( X ) and misses ( O )
void PrintBoard();
// Resets the board for both players before new games begin
void ResetBoard();
// Marks both boards after each guess
void MarkBoard(bool hit, Point guessCoordinate);
// Returns TRUE if the user has guessed the given coordinate
bool CheckGuess( Point guessCoordinate );
private:
// Board used for determining whether the user has guessed a certain position yet or not
bool playerBoard[BOARD_WIDTH][BOARD_LENGTH] = {false};
// Board used soley for output
// KEY: 0 = not yet guessed, 1 = hit, 2 = miss
// intialize all spaces to 0 to show that no guesses have been made yet
int outputBoard[10][10] = { 0 };
};
Board.cpp
// Board.cpp - Board class function implementation
#include "Board.h"
Board::Board()
{
}
// Prints the output board to console
void Board::PrintBoard()
{
// Print column numbers
cout << " \t" << " " << 1;
for( int number = 2; number < 11; number++)
cout << " " << number;
cout << endl;
// Print board itself
// i = row number, j = column number
for( int i = 0; i < 10; i++)
{
// int i can double as a row and column counter for checking if a space has been hit
/*cout << " \t";
// Print row lines
for( int k = 1; k < 11; k++)
cout << " __";*/
cout << endl;
// Print row number
cout << i+1 << " ";
cout << "\t";
// Print columns
for( int j = 0; j < 10; j++)
{
cout << "|";
// INSERT CODE THAT PLACES X OR O IF GUESS IS HIT OR SHIP
if( outputBoard[i][j] == 0 )
cout << WATER;
if( outputBoard[i][j] == 1 )
cout << HIT;
if( outputBoard[i][j] == 2 )
cout << MISS;
}
cout << "|";
cout << endl;
}
cout << endl;
}
void Board::MarkBoard(bool hit, Point guessCoordinate)
{
// First mark the board to show the player has guessed this coordinate
playerBoard[guessCoordinate.X][guessCoordinate.Y] = true;
if( hit == true )
{
// Show that the player hit a ship
outputBoard[guessCoordinate.X][guessCoordinate.Y] = 1;
}
else
{
// Show that the player missed the ship
outputBoard[guessCoordinate.X][guessCoordinate.Y] = 2;
}
}
bool Board::CheckGuess(Point guessCordinate)
{
bool previouslyGuessed = false;
// If the given point has already been guessed, make the function return true
if( playerBoard[guessCordinate.X][guessCordinate.Y] )
{
previouslyGuessed = true;
}
else
{
previouslyGuessed = false;
}
return previouslyGuessed;
}
Ship.h
#pragma once
#include <string>
#include "Point.h"
using namespace std;
#define SHIP_TYPES 5
#define MAX_LENGTH 5
enum DIRECTION {HORIZONTAL,VERTICAL};
class Ship
{
public:
// Constructor
Ship();
// Function to initially set all ship to the correct values
void LoadShips( Ship ship[SHIP_TYPES] );
// Function which gives ships their location points and placement orientation
void FillShipData( DIRECTION direction, Point coordinate );
bool isSunk();
bool isHit( Point guess, Ship ship[SHIP_TYPES] );
string GetName()
{ return Name; }
private:
// Ship name
string Name;
// How many spaces the ship occupies
int Length;
// Determines whether a ship lies vertically or horizontally on the board
DIRECTION Direction;
// Holds the coordinates that the ship occupies
Point spaceOccupied[MAX_LENGTH];
};
Ship.cpp
#include "Ship.h"
Ship::Ship()
{
}
void Ship::LoadShips(Ship ship[SHIP_TYPES])
{
//Sets the default data for the ships
//we plan to include in the game
//IMPORTANT!! > MUST MATCH SHIP_TYPES -Default=5 (0-4)
ship[0].Name = "Cruiser"; ship[0].Length = 2;
ship[1].Name = "Frigate"; ship[1].Length = 3;
ship[2].Name = "Submarine"; ship[2].Length = 3;
ship[3].Name = "Escort"; ship[3].Length = 4;
ship[4].Name = "Battleship"; ship[4].Length = 5;
}
void Ship::FillShipData( DIRECTION direction, Point coordinate )
{
Direction = direction;
int x,y;
// If the ship will be laid horizontally, give it the initial point plus the x-coordinates to its right
if( Direction == HORIZONTAL )
{
while( coordinate.X+Length >= BOARD_WIDTH || coordinate.X < 0 || coordinate.Y < 0 || coordinate.Y >= BOARD_LENGTH )
{
cout << "Your ship will not be entirely on the board when placed this way. Please choose a new row number and column number separated by a space (ex: x y): ";
cin >> x >> y;
coordinate.X = x;
coordinate.Y = y;
}
for( int i = 0; i < Length; i++ )
{
spaceOccupied[i] = coordinate;
coordinate.X++;
}
}
// If the ship will be laid vertically, give it the initial point plus the y-coordinates below it
else
{
// Be sure the give point will contain and the ship
while( coordinate.Y+Length >= BOARD_LENGTH || coordinate.X < 0 || coordinate.Y < 0 || coordinate.X >= BOARD_WIDTH )
{
cout << "Your ship will not be entirely on the board when placed this way. Please choose a new row number and column number separated by a space (ex: x y): ";
cin >> x >> y;
coordinate.X = x;
coordinate.Y = y;
}
for( int i = 0; i < Length; i++ )
{
spaceOccupied[i] = coordinate;
coordinate.Y++;
}
}
}
// use throwaway to call, one user's guess and the other user's ships
//
bool Ship::isHit( Point guess, Ship ship[SHIP_TYPES] )
{
bool hit = false;
// For loop to examine each ship
for( int i = 0; i < SHIP_TYPES && hit==false; i++ )
{
// For loop to go through each point the ship occupies
for( int j = 0; j < ship[i].Length && hit==false; j++ )
{
// If the player's guess matches a point the ship is located on, it has been hit
if( ship[i].spaceOccupied[j] == guess )
{
hit = true;
// Inform player they landed a hit
cout << "Ship: " << ship[i].Name << " has been hit!\n";
}
}
}
// If the player has missed all ships, inform them
if( hit == false )
cout << "Missed.\n";
return hit;
}
最后是Point.h
#pragma once
#include <iostream>
using namespace std;
#define BOARD_LENGTH 10
#define BOARD_WIDTH 10
struct Point
{
// A location on the grid defined
// by X(horizontal) Y(vertical) coordinates
int X;
int Y;
bool operator == (const Point& compareTo) const
{
return ( (X == compareTo.X) && (Y == compareTo.Y) );
}
};
ostream& operator <<(ostream& out, const Point& myPoint)
{
out << "(" << myPoint.X << "," << myPoint.Y << ")";
return out;
}
我的主要功能只包括Board.h和Ship.h,没有函数声明。 任何帮助将不胜感激!
答案 0 :(得分:7)
愚蠢的一个,但要确保你没有错误地#imp一个.m文件
答案 1 :(得分:2)
问题在于您正在重新定义main.cpp Board.cpp中的operator<<(ostream&, const Point&)
和Ship.cpp,方法是在每个中包含Point.h。
您最容易通过在Point.h中将其inline
解决来解决此问题。
inline ostream& operator <<(ostream& out, const Point& myPoint) // << add inline
当您在错误输出中看到这些奇怪的符号名称时,一个技巧是使用终端中的c++filt
来更轻松地查看导致问题的函数名称或符号。例如,这将“解开”符号名称,在终端中尝试:
phillip / $ c++filt __ZlsRNSt3__113basic_ostreamIcNS_11char_traitsIcEEEERK5Point
operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, Point const&)
phillip / $
答案 2 :(得分:1)
在这里添加inline
。
inline ostream& operator <<(ostream& out, const Point& myPoint)
^^^^^^
{
out << "(" << myPoint.X << "," << myPoint.Y << ")";
return out;
}
答案 3 :(得分:0)
您可能在Xcode项目中有目标文件(.o)。 Xcode不喜欢这个。删除目标文件,代码应该编译。