结构的多重定义错误,但我在任何地方都看不到错误(C++)

Posted

技术标签:

【中文标题】结构的多重定义错误,但我在任何地方都看不到错误(C++)【英文标题】:Error multiple definition of struct, but i dont see the error anywhere ( C++ ) 【发布时间】:2020-01-05 23:02:07 【问题描述】:

制作了一个结构,编译了我的程序,完美运行,没有改变任何东西,关闭了vm,重新启动了vm和vsc,然后再次在控制台中做了,它出现了这个错误

1 warning generated.
linking build/main.o
build/Game.o:(.bss+0x60): multiple definition of `scoreArray'
build/main.o:(.bss+0x10): first defined here
clang-5.0: error: linker command failed with exit code 1 (use -v to see 
invocation)
Makefile:33: recipe for target 'build/2048' failed
make: *** [build/2048] Error 1

这是我的代码,我看不到任何重新定义它的东西,请有人帮我找出它, 这是头文件和它使用的源文件

main.cpp

/**
 * File: main.cpp
 * Author: not lettin u know :)
 * Date: 20-11-2019
 * Desc:
 * Copyright: University of West of England 2017
 */
#include <stdio.h>
#include <cstdio>
#include <stdlib.h>
// include the UFCFGL301's standard library
#include <ufcfgl-30-1.h>
#include <iostream>
#include <time.h>
#include "Grid.h"
#include "Game.h"
// uncomment if you want to use the graphics library
#include <graphics.h>

using namespace std;
using namespace uwe;

/**
 * main routine, implements ...
 * @return      success
 */
int main(void) 

    srand(time(0));
    Game game;
// -------Initialising Game-------
    while(1)

        game.chooseFunction();
        grid.totalScore = 0;
        grid.initGrid();
        grid.addValue();
        cout << "\033[2J"; // this clears the terminal
        cout << "\nPlayer Score : " << grid.totalScore << "\n";
        std::cout << "\nMoves = " << grid.moves << "\n\nlast input = N/A \n";
        grid.setScore(grid.score);
        grid.drawGrid();


    // This launches graphics window where all keypresses are inputted
    // this is also where we start the lambda functions in a loop 

        initialiseGraphics(600,400);
        loop (
            [&]()
            ,

            [&](keyPress keyPress)

    // w a s d are also inputted into an integer as their respective ascii value
    // so this allows the use of w a s d and also the arrow keys in controlling
    // the moves of the player

                int kpVal = keyPress.getKeyCode();

                if ( kpVal == 'q' )
                    return true;
                
                if ( kpVal == 'w' || kpVal == keyPress::upKey )
                    cout << "\033[2J"; // this clears the terminal
                    grid.shiftUp();
                    cout << "Player Score : " << grid.totalScore << "\n";
                    std::cout << "\nMoves = " << grid.moves 
                              << "\n\nlast input = UP \n";
                    grid.setScore(grid.score);
                    grid.drawGrid();
                    game.checkGameState();
                    if(game.gameFinished == true)
                        return true;
                    
                
                if ( kpVal == 'a' || kpVal == keyPress::leftKey )
                    cout << "\033[2J"; // this clears the terminal
                    grid.shiftLeft();
                    cout << "Player Score : " << grid.totalScore << "\n";
                    std::cout << "\nMoves = " << grid.moves  
                              << "\n\nlast input = LEFT \n";
                    grid.setScore(grid.score);
                    grid.drawGrid();
                    game.checkGameState();
                    if(game.gameFinished == true)
                        return true;
                    
                
                if ( kpVal == 's' || kpVal == keyPress::downKey )
                    cout << "\033[2J"; // this clears the terminal
                    grid.shiftDown();
                    cout << "Player Score : " << grid.totalScore << "\n";
                    std::cout << "\nMoves = " << grid.moves 
                              << "\n\nlast input = DOWN \n";
                    grid.setScore(grid.score);
                    grid.drawGrid();
                    game.checkGameState();
                    if(game.gameFinished == true)
                        return true;
                    
                
                if ( kpVal == 'd' || kpVal == keyPress::rightKey )
                    cout << "\033[2J"; // this clears the terminal
                    grid.shiftRight();
                    cout << "Player Score : " << grid.totalScore << "\n";
                    std::cout << "\nMoves = " << grid.moves 
                              << "\n\nlast input = RIGHT \n";
                    grid.setScore(grid.score);
                    grid.drawGrid();
                    game.checkGameState();
                    if(game.gameFinished == true)
                        return true;
                    
                
                return false;
            
        );
    

游戏.h

#pragma once
#include <cstdio>
#include <string>
#include <graphics.h>
#include "Grid.h"

class Game

public:

    bool canMove();
    bool checkWin();
    bool checkLoss();
    void checkGameState();
    void chooseFunction();
    void printHighScores();
    void writeHighScore();

    bool gameFinished = false;

private:

;
extern Game game;

struct highScore 
    int score;
    std::string name;
;   

游戏.cpp

#include "Grid.h"
#include "Game.h"
#include <sstream>
#include <unistd.h>
#include <iostream>
#include <cstdio>
#include <graphics.h>
#include <fstream>
#include <string>
#include <algorithm> //std::sort for array of structs sorting based on struct
                     // integer

Grid grid;
highScore scoreArray[100];

// functions to check game state for win or loss or can make moves

bool Game::canMove()
    bool canMove = false;
    for(int x = 0; x < Grid::tilesWide; x++)
        for(int y = 0; y < Grid::tilesHigh; y++)
            if (grid.grid[x][y] == Grid::emptyCell) 
                canMove = true;
                return canMove;
            

// multiple if statements due to if grid[3][1] was being checked with
// grid[3+1][1] then it would loop around and check against grid[1][2] 
// for an unknown reason, so to combat this i had to check specifically against
// the edge of the board 

            else if(y == 3 && x < 3)
                if( grid.grid[x][y] == grid.grid[x+1][y] )
                    canMove = true;
                    return canMove;
                
            
            else if(x == 3 && y < 3)
                if( grid.grid[x][y] == grid.grid[x][y+1] )
                    canMove = true;
                    return canMove;
                
            
            else if( ( x < 3 && y < 3 ) && 
                    (grid.grid[x][y] == grid.grid[x][y+1] ||
                     grid.grid[x][y] == grid.grid[x+1][y]) ) 

                canMove = true;
                return canMove;
            
        
    
    return canMove;


bool Game::checkWin()
    bool win = false;
    for(int x = 0; x < Grid::tilesWide; x++)
        for(int y = 0; y < Grid::tilesHigh; y++)
            if(grid.grid[x][y] == 2048)
                win = true;
                return win;
            
        
    
    return win;


bool Game::checkLoss()
    bool loss = false;
    if(canMove() == false )
        loss = true;
        return loss;
    
    return loss;


void Game::checkGameState()
    if(checkWin() == true) 
        std::cout << "\n\n--------YOU WIN--------\n\n";
        gameFinished = true;
        writeHighScore();
    
    else if(checkLoss() == true) 
        std::cout << "\n\n--------YOU LOSE--------\n\n";
        gameFinished = true;
    


// functions for initializing game/options

void Game::chooseFunction()
    while(1)
        int function = 0;
        std::cout << "\nPlease Choose A Function\n1) Play Game\n2) High Scores"
                  << "\n3) Exit Program";
        std::cout << "\nFunction : ";
        std::cin  >> function;
        if (std::cin.fail() || function < 1 || function > 3) 
            std::cin.clear();                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
            std::cin.ignore(1000,'\n'); // this is to stop the validation from
                                   // looping for each wrong character entered
            std::cout << "Not a valid option, Please re-enter \n\n" ;
            sleep(1); 

        
        else if (function == 1) 
            std::cout << "------Launching Game------\n\n";
            std::cout << "---------LOADING---------\n";
            for(int x=0;x < 5;x++)
                std::cout << "|||||" << std::flush;
                sleep(1);
            
            return ;
        

        else if (function == 2) 
            std::cout << "---Printing High Scores---\n";
            std::cout << "---------LOADING---------\n";
            for(int x=0;x < 5;x++)
                std::cout << "|||||" << std::flush;
                sleep(1);
            
            printHighScores();
            sleep(10);
        

        else if (function == 3) 
            std::cout << "-------Now Exiting------- \n\n" << std::flush ;
            std::cout << "---------LOADING---------\n";
            for(int x=0;x < 5;x++)
                std::cout << "|||||" << std::flush;
                sleep(1);
            
            exit(0);
        

    


// This function is called upon a win, and writes the high score ,of those who
// win the game, into a text file under the format of  SCORE - NAME

void Game::writeHighScore()
    std::string name;
    std::cout << "\nEnter Name To Store High Score ( Max 16 Characters )\n"
              << "Name : ";
    std::getline(std::cin,name);
    // this is to stop the string being over 16 characters
    if(std::cin.fail() || name.length() > 16)
        std::cout << "\n\nPlease Enter A Max of 16 Characters\n\n";
        writeHighScore();
        return;
    
    else
// This opens the output stream to the high scores text file
// and immediately points to the next free line in the file
        std::ofstream HighScore;
        HighScore.open ("HighScores.txt", std::ios::app);
        HighScore << grid.totalScore << "   "<< name << std::endl; 
        HighScore.close();
        return;
    


// simple comparator function to be used with std::sort in order to sort
// the array of structs containing scores and their respective player names

bool sortScore(highScore a,highScore b)
    return a.score > b.score; 
 

// this function prints the high scores from the text file, however
// im not sure how to sort a text file each time its appended, so instead
// when this function is called, it seperates the lines of the files into
// the score and their respective player name, these are stored in a struct
// object for each line, and then the array of structs is sorted using
// std::sort and the comparator function and then the first 10 scores and names
// in the struct array are printed, TLDR, prints Top 10 scores :) 
// 
// not on the spec for the assignment but i enjoyed learning about how
// i would go about making something like this :) 

void Game::printHighScores()  // function to choose and print ascii art
    std::ifstream highScores;
    highScores.open("HighScores.txt");
    std::string line;
    int i=0;
    if(!highScores)
        std::cout << "\nCould Not Open HighScores.txt";
        sleep(2);
        return;
    
    else
        while(getline(highScores, line))
            std::istringstream iss(line);
            int score;
            std::string name;

// this seperates out the score and the name string from each line in the file
            if(!(iss >> score && iss.ignore() && std::getline(iss,name)))
                break;
            
// this adds to the array of structs defined in the header file
            scoreArray[i].score = score;
            scoreArray[i].name = name;
            i++;
        
        std::sort(&scoreArray[0],&scoreArray[100],sortScore);
    

// and finally... this prints the top 10 scores

    std::cout << "\n\n-------HIGH SCORES-------\n\n";
    for(int i=0; i<10; i++)
        std::cout <<i+1<<")  "<<scoreArray[i].score<<" - "<<scoreArray[i].name
        <<"\n";
    

【问题讨论】:

问题标题中无需添加unsolvedsolved。这就是接受答案的目的。 哦,我只是以为人们正在阅读它,看到一个有效的答案,并没有发布任何可能有帮助的东西,因为他们可能认为有效的答案解决了问题 【参考方案1】:

线

highScore scoreArray[100]; 

只要包含此标头,您的标头就会声明一个变量。我假设该标头包含在多个源文件中。

将其移动到.cpp 中并将extern 添加到标题中。

基本上,对于包含此标头的每个源文件,您都在声明一个名为 scoreArray 的变量。每个包含此标头的.cpp 都将声明自己的scoreArray。链接器在进行链接时会遇到两个具有相同名称的变量,并且无法确定哪个是“正确的”,因此它放弃并生成您所看到的错误。

因此,您需要将定义移动到 .cpp 中,并在标题中将其作为外部引用。 (有几种不同的方法。选择最适合您的方法。)

【讨论】:

哦,所以在源文件的头文件中声明结构数组不起作用? 您的标头可以包含数组的extern 声明,但如果标头被多个源文件使用,则它实际上必须在 .cpp 中定义。预处理时,编译器基本上在编译之前将任何#include'd 文件的内容粘贴到包含源中。 也将 highScore scoreArray[100] 移动到 cpp 文件中不起作用,它仍然显示多个定义:S @meme 你注释掉声明会发生什么? 未声明标识符'scoreArray'的一堆错误对我来说毫无意义:(

以上是关于结构的多重定义错误,但我在任何地方都看不到错误(C++)的主要内容,如果未能解决你的问题,请参考以下文章

错误 TS2318:找不到全局类型“对象”

诊断 CUDA 内核问题

使用 Laravel 使自定义类在任何地方可用

Symfony4 Twig模板错误:变量“小部件”不存在

找不到方法 moneyToMicros((class))

Oracle to_date() 输出错误