我正在尝试在Xcode 4.6.3中构建一个C ++项目。
在我的项目中(一个非常简单的OpenGL游戏的开头)我有两个文件:
textures.h:
#pragma once
#include <GLUT/GLUT.h>
void load(); // load textures
GLuint dirt, water; // variables to store texture handles
textures.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()函数作为初始化的一部分,并访问dirt变量以绑定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
,并且我已经在工作区中搜索了“污垢”等等,并且没有其他定义。我的其他标题工作正常,甚至是多次包含的标题。我使用不同的关键字多次搜索此问题,并查看了其他类似的问题,但我发现的只有this SO question。
我之前在Xcode中遇到过其他“随机”错误 - 例如,一个项目一直试图使用我删除的动态库并用静态库替换。即使我创建了一个全新的项目,错误仍然存在。它在从终端手动编译时起作用。
我错过了什么?
答案 0 :(得分: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文件中,但是不起作用。你不是第一个误解这一点的人。