C ++ #include导致'重复符号'

时间:2018-04-09 21:01:38

标签: c++ cmake

我正在开始一个C ++ OpenGL项目,我开始使用两个.cpp文件,Sceneboilerplate(没有.h文件!)。 boilerplate包含简单设置环境的OpenGL过程。

我以为我会将它们移到这个单独的文件中,以便在Scene中为自己留出更多空间,但现在我已经这样做并尝试在#includeScene此文件,我在链接时遇到“重复符号”错误,例如

Scanning dependencies of target Coursework
[ 33%] Building CXX object CMakeFiles/Coursework.dir/Scene.cpp.o
[ 66%] Linking CXX executable Coursework
duplicate symbol __Z12checkGLErrorv in:
    CMakeFiles/Coursework.dir/Scene.cpp.o
    CMakeFiles/Coursework.dir/boilerplate.cpp.o
duplicate symbol __Z5setupv in:
    CMakeFiles/Coursework.dir/Scene.cpp.o
    CMakeFiles/Coursework.dir/boilerplate.cpp.o
duplicate symbol _height in:
    CMakeFiles/Coursework.dir/Scene.cpp.o
    CMakeFiles/Coursework.dir/boilerplate.cpp.o
...

每个“重复符号”都来自boilerplate.cpp中的定义。

为什么我会收到这些错误?我认为#include实际上与将文件的代码复制并粘贴到当前文件中是一样的,但是当我实际执行此操作时,它构建得很好。

我正在使用CMake构建,以防这是相关的(这是一个链接错误,所以它可能与此有关吗?)。

以下是供参考的文件,

Scene.cpp:

#include <iostream>
#include <glut/glut.h>

#include "boilerplate.cpp"

void draw() {

    glClearColor(0.2f, 0.2f, 0.2f, 1.f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // make beautiful models

    glutSwapBuffers();
}

int main(int argc, char **argv) {

    glutInit(&argc, argv);         
    setup();                        

    glutDisplayFunc(draw);          

    checkGLError();                 
    glutReshapeFunc(reshape);
    glutMainLoop();                 

    return 0;
}

boilerplate.cpp:

#include <glut/glut.h>
#include <cstdio>

int width, height;

void checkGLError() {

    int e = 0;
    GLenum error = glGetError();

    while (GL_NO_ERROR != error) {
        e++;
        printf("GL Error %i: %s\n", e, gluErrorString(error));
        error = glGetError(); 
    }
}

void setup() {

    width = 800;                                    
    height = 800;                                   

    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE);  
    glutInitWindowSize(width, height);           
    glutCreateWindow("Coursework");                 
}

void reshape(int _width, int _height) {

    height = _height;
    width = _width;

    GLdouble aspect = static_cast<GLdouble>(width) / static_cast<GLdouble>(height);

    glMatrixMode(GL_PROJECTION);

    glLoadIdentity();  
    gluPerspective(45.0, aspect, 1, 1000);

    glMatrixMode(GL_MODELVIEW);  
}

的CMakeLists.txt:

cmake_minimum_required(VERSION 3.9)
project(Coursework)

set(CMAKE_CXX_STANDARD 11)

find_package(OpenGL REQUIRED)
find_package(GLUT REQUIRED)

# Put directories in project's 'include path'
include_directories(${OPENGL_INCLUDE_DIRS} ${GLUT_INCLUDE_DIRS})

# Declare the var 'SOURCE_FILES', and give it all relevant source filenames
set(SOURCE_FILES Scene.cpp boilerplate.cpp)

add_executable(${PROJECT_NAME} ${SOURCE_FILES})

target_link_libraries(${PROJECT_NAME} ${OPENGL_LIBRARIES} ${GLUT_LIBRARY})

2 个答案:

答案 0 :(得分:2)

当你说#include - 就像复制粘贴相应位置的内容时,你是对的。

但是如果你包含一个不仅包含声明和类定义的文件,还包含变量定义或函数/方法的实现,那么你可能会遇到麻烦......

a。)您要么在其他几个文件中包含相同的boilerplate.cpp;这将导致重新定义相同的事物 - &gt;重复的符号错误

b。)您只在一个文件中包含boilerplate.cpp,但编译器也将boilerplate.cpp文件视为单独的翻译单元 - &gt;重复的符号

所以避免包括.cpp文件;而是将.cpp文件提供的函数作为函数原型(即没有正文的函数)暴露在适当的.h文件中;那么只包括.h文件。

答案 1 :(得分:0)

我的问题是我希望将#include简单地用作复制粘贴工具,但我将CMake boilerplate.cpp作为单独的可执行文件,并尝试将其链接< em>和 #include它在Scene.cpp中导致了这些重复的符号错误。

从CMake中删除boilerplate.cpp,即从

中删除它
set(SOURCE_FILES Scene.cpp boilerplate.cpp)

解决了这个问题并允许我构建它。

但正如评论所说,“正确的&#39;这样做的方法是给boilerplate.cpp一个头文件并包含它。在我读到这篇文章之前,我无法理解为什么这是首选方式:

Why should I not include cpp files and instead use a header?