2013-09-21 29 views
5

Tôi đang cố gắng xây dựng một dự án C++ trong Xcode 4.6.3.Ký hiệu trùng lặp ngẫu nhiên trong xcode (C++)

Trong dự án của tôi (sự khởi đầu của một trò chơi rất đơn giản OpenGL) Tôi có hai tập tin:

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"); 
} 

Ở đây util.h định nghĩa hàm util :: loadTexture.

Có hai tệp bao gồm textures.h. Hàm main (hàm main.cpp) đầu tiên gọi hàm load() như một phần của khởi tạo và truy cập biến số bẩn để liên kết kết cấu Soil.png. Thứ hai (Chunk.cpp) bao gồm textures.h, nhưng không thực sự truy cập bất cứ thứ gì từ nó.

Khi tôi cố gắng xây dựng dự án, nó mang lại cho tôi những lỗi sau:

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) 

Tôi hiểu rằng điều này có nghĩa là một bản sao ở đâu đó, hoặc một tiêu đề được bao gồm nhiều lần. Nhưng tất cả các tiêu đề của tôi đều sử dụng #pragma once và tôi đã thực hiện tìm kiếm trong không gian làm việc cho "bụi bẩn" và như vậy và không có định nghĩa nào khác. Các tiêu đề khác của tôi hoạt động tốt, ngay cả các tiêu đề được bao gồm nhiều lần. Tôi đã googled vấn đề này nhiều lần với các từ khóa khác nhau và đã xem xét các câu hỏi tương tự khác, nhưng tất cả những gì tôi thấy là this SO question.

Tôi đã gặp phải các lỗi "ngẫu nhiên" khác trước trong Xcode - ví dụ: một dự án tiếp tục cố sử dụng thư viện động mà tôi đã xóa và thay thế bằng một thư tĩnh. Lỗi vẫn tồn tại, ngay cả khi tôi tạo ra một dự án hoàn toàn mới. Nó hoạt động khi biên dịch thủ công từ Terminal.

Tôi đang thiếu gì?

Trả lời

5

#pragma once không dừng tệp tiêu đề được bao gồm nhiều lần.

Nó dừng tệp tiêu đề được bao gồm nhiều lần khi biên soạn một tệp. Bạn có (ít nhất) ba tệp để bạn khai báo cùng một biến 3 lần.

Không đặt định nghĩa biến trong tệp tiêu đề. Làm điều này thay vì

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


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

Bạn có thể có nhiều tuyên bố của một biến như bạn muốn (miễn là họ đều giống hệt nhau), vì vậy nó là OK để đưa tờ khai trong một tập tin tiêu đề, bạn phải có đúng một định nghĩa biến, vì vậy bạn đặt nó vào một tệp .cpp.

Điều quan trọng cần nhớ là mọi tệp .cpp được biên dịch hoàn toàn độc lập với mọi tệp .cpp khác, điều này được gọi là biên dịch riêng biệt. Vì vậy, ý tưởng của bạn rằng #pragma once sẽ ngăn tệp tiêu đề bị bao gồm bởi một tệp .cpp chỉ vì tệp đã được đưa vào tệp .cpp khác không hoạt động. Bạn không phải là người đầu tiên hiểu nhầm điều này.

+0

Tôi đã thử thay thế #pragma một lần cho #ifndef #define #endif mà Xcode ban đầu tạo và nó vẫn không hoạt động ... – qxz

+0

Vâng #ifndef ...hoạt động chính xác giống như #pragma một lần và không thực hiện những gì bạn cho rằng nó nên làm cho cùng một lý do. Những gì tôi đăng không phải là một mẹo, đó là cách chính xác để sử dụng các biến toàn cầu. – john

+0

Đừng ngừng sử dụng #pragma một lần hoặC#ifndef ... nó chỉ giải quyết được một vấn đề khác với những gì bạn nghĩ. – john