首页 > 解决方案 > 仅在 CodeBlocks 中出现“多重定义”错误

问题描述

我正在使用 MVC 构建井字游戏。代码如下:

主.cpp:

#include "controller.cpp"

int main()
{
    Controller controller;
    controller.start_game();
}

控制器.hpp:

#ifndef controllerTTT
#define controllerTTT

#include <iostream>
#include <array>
#include <string>
#include "common.hpp"
#include "model.cpp"
#include "view.cpp"
#define BOARD_SIZE 3

class Controller
{
    private:
        Model model;
        View view;
        bool player_interaction(Player);
        void single_game();
    public:
        void start_game();
};

#endif

控制器.cpp:

#include "controller.hpp"

bool Controller::player_interaction(Player player){
    //code eliminated in order to not post 300 lines of code
}

void Controller::single_game(){
    //code eliminated in order to not post 300 lines of code
}

void Controller::start_game(){
    //code eliminated in order to not post 300 lines of code
}

模型.hpp:

#ifndef modelTTT
#define modelTTT

#include <array>
#include "common.hpp"
#define BOARD_SIZE 3

class Model
{
    private:
        Player board[BOARD_SIZE][BOARD_SIZE];
    public:
        Model();
        void do_move(Move_input, Player);
        bool legal_move(Move_input);
        Outcome outcome();
        std::array<Player, BOARD_SIZE*BOARD_SIZE> get_board();
        void reset();
};

#endif

模型.cpp:

#include "model.hpp"

Model::Model()
{
    for(int row=0; row<BOARD_SIZE; ++row)
    {
        for(int column=0; column<BOARD_SIZE; ++column)
        {
            this->board[row][column]=Player::none;
        }
    }
}

void Model::do_move(Move_input move_input , Player player)
{
    //code eliminated in order to not post 300 lines of code
}

bool Model::legal_move(Move_input move_input)
{
    //code eliminated in order to not post 300 lines of code
}

Outcome Model::outcome()
{
    //code eliminated in order to not post 300 lines of code
}

std::array<Player, BOARD_SIZE*BOARD_SIZE> Model::get_board(){
    //code eliminated in order to not post 300 lines of code
}

void Model::reset(){
    //code eliminated in order to not post 300 lines of code
}

视图.hpp:

#ifndef viewTTT
#define viewTTT

#include <iostream>
#include <array>
#include <windows.h>
#include <string>
#include "common.hpp"
#define BOARD_SIZE 3

class View
{
    public:
        void output_board(std::array<Player, BOARD_SIZE*BOARD_SIZE>);
        void output_message(std::string);
        void output_outcome(Outcome);
        void wait(int miliseconds);
        void reset();
        Move_input get_move();
        std::string get_message();
};

#endif

视图.cpp:

#include "view.hpp"

void View::output_board(std::array<Player, BOARD_SIZE*BOARD_SIZE> board){
    //code eliminated in order to not post 300 lines of code
}

void View::output_message(std::string message){
    //code eliminated in order to not post 300 lines of code
}

void View::output_outcome(Outcome outcome){
    //code eliminated in order to not post 300 lines of code
}

void View::wait(int miliseconds){
    //code eliminated in order to not post 300 lines of code
}

void View::reset(){
    //code eliminated in order to not post 300 lines of code
}

Move_input View::get_move(){
    //code eliminated in order to not post 300 lines of code
}

std::string View::get_message(){
    //code eliminated in order to not post 300 lines of code
}

common.hpp:

#pragma once

enum class Player
{
    none='-',
    player1='X',
    player2='O'
};

enum class Outcome
{
    none,
    win1='X',
    win2='O',
    draw
};

struct Move_input{
    int row,column;
};

在 Code::Blocks 中编译时出现以下错误:

但是,当我使用此命令在控制台中构建它时,g++ -std=c++11 main.cpp它工作得很好。那么我的代码有什么问题?

标签: c++classcompiler-errors

解决方案


问题有两个方面:

  • 首先,如前所述,#include您使用源文件而不是头文件。

  • 其次,您的 IDE(代码块)项目已经列出了源文件(它必须列出,否则您不会得到错误)。

在解释为什么上述两点共同作用会导致您遇到的问题之前,您需要了解如何使用 C++ 构建应用程序。要制作 C++ 应用程序,您需要执行三个步骤:

  1. 编辑一个或多个源文件
  2. 将源文件编译成目标文件
  3. 将目标文件链接到单个可执行文件中。

即使您没有显式创建目标文件(如使用g++ -std=c++11 main.cpp命令),目标文件也是由g++前端程序隐式创建的。

现在回到你遇到的问题......

因为您的 CodeBlocks 项目列出了所有源文件,所以它们将显式构建到目标文件中,然后链接到最终的可执行程序中。问题是许多符号已经在单个main.o目标文件中定义,因为您是#include源文件。因此(例如)符号Controller::single_game将在 object filemain.o object file中定义controller.o。这是不允许的。

你可以通过只在任何地方包含头文件来解决这个问题。文件中的源代码.cpp将由 CodeBlocks 为您构建和链接。


推荐阅读