5

我正在尝试在 Xcode 4.6.3 中构建一个 C++ 项目。

在我的项目(一个非常简单的 OpenGL 游戏的开始)中,我有两个文件:

纹理.h:

#pragma once

#include <GLUT/GLUT.h>

void load(); // load textures

GLuint dirt, water; // variables to store texture handles

纹理.cpp:

#include "textures.h"

#include "util.h"

void textures::load() {
    dirt = util::loadTexture("/Some/Path/Soil.png");
    water = util::loadTexture("/Some/Path/Water_fresh.png");
}

这里 util.h 定义了 util::loadTexture 函数。

有两个文件包含 textures.h。第一个 (main.cpp) 调用 load() 函数作为初始化的一部分并访问污垢变量以绑定 Soil.png 纹理。第二个(Chunk.cpp)包括textures.h,但实际上还没有从它访问任何东西。

当我尝试构建项目时,它给了我以下错误:

duplicate symbol _dirt in:
    /Users/me/Library/Developer/Xcode/DerivedData/OpenGL_Testing-epporrdukapbwzawfhiwnlztzdns/Build/Intermediates/OpenGL Testing.build/Debug/OpenGL Testing.build/Objects-normal/x86_64/main.o
    /Users/me/Library/Developer/Xcode/DerivedData/OpenGL_Testing-epporrdukapbwzawfhiwnlztzdns/Build/Intermediates/OpenGL Testing.build/Debug/OpenGL Testing.build/Objects-normal/x86_64/Chunk.o
duplicate symbol _water in:
    /Users/me/Library/Developer/Xcode/DerivedData/OpenGL_Testing-epporrdukapbwzawfhiwnlztzdns/Build/Intermediates/OpenGL Testing.build/Debug/OpenGL Testing.build/Objects-normal/x86_64/main.o
    /Users/me/Library/Developer/Xcode/DerivedData/OpenGL_Testing-epporrdukapbwzawfhiwnlztzdns/Build/Intermediates/OpenGL Testing.build/Debug/OpenGL Testing.build/Objects-normal/x86_64/Chunk.o
duplicate symbol _dirt in:
    /Users/me/Library/Developer/Xcode/DerivedData/OpenGL_Testing-epporrdukapbwzawfhiwnlztzdns/Build/Intermediates/OpenGL Testing.build/Debug/OpenGL Testing.build/Objects-normal/x86_64/main.o
    /Users/me/Library/Developer/Xcode/DerivedData/OpenGL_Testing-epporrdukapbwzawfhiwnlztzdns/Build/Intermediates/OpenGL Testing.build/Debug/OpenGL Testing.build/Objects-normal/x86_64/textures.o
duplicate symbol _water in:
    /Users/me/Library/Developer/Xcode/DerivedData/OpenGL_Testing-epporrdukapbwzawfhiwnlztzdns/Build/Intermediates/OpenGL Testing.build/Debug/OpenGL Testing.build/Objects-normal/x86_64/main.o
    /Users/me/Library/Developer/Xcode/DerivedData/OpenGL_Testing-epporrdukapbwzawfhiwnlztzdns/Build/Intermediates/OpenGL Testing.build/Debug/OpenGL Testing.build/Objects-normal/x86_64/textures.o
ld: 4 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

我知道这意味着某处存在重复,或者标题包含多次。但是我所有的标题都使用#pragma once,并且我已经在工作区中搜索了“污垢”等,并且没有其他定义。我的其他标题工作正常,即使是多次包含的标题。我用不同的关键字多次搜索这个问题,并查看了其他类似的问题,但我发现的只是这个 SO question

我之前在 Xcode 中遇到过其他“随机”错误——例如,一个项目一直在尝试使用我已删除并用静态库替换的动态库。即使我创建了一个全新的项目,错误仍然存​​在。从终端手动编译时它可以工作。

我错过了什么?

4

1 回答 1

5

#pragma once不会阻止头文件被多次包含。

它会在编译单个文件时停止包含多次头文件。你有(至少)三个文件,所以你要声明相同的变量 3 次。

不要将变量定义放在头文件中。改为这样做

// textures.h
extern GLuint dirt, water; // variable declarations


// textures.cpp
GLuint dirt, water; // variable definitions

您可以根据需要拥有任意数量的变量声明(前提是它们都相同),因此可以将声明放在头文件中,您必须只有一个变量定义,因此将其放在 .cpp 文件中。

要记住的关键是每个 .cpp 文件都完全独立于其他每个 .cpp 文件进行编译,这称为单独编译。因此,您认为#pragma once仅仅因为它已包含在另一个 .cpp 文件中而阻止头文件包含在一个 .cpp 文件中的想法是行不通的。你不是第一个误解这一点的人。

于 2013-09-21T06:19:32.267 回答