2016-08-17 1 views
3

이전 버전의 Cocos2dx를 사용하여 게임을 작성하고 VS 2013으로 컴파일했습니다. CMake 및 Qt Creator를 두 컴파일러 버전. Cocos2dx v3.12가 나왔을 때, 나는 내 게임에 해당 버전에 lib 디렉토리를 업그레이드하기로 결정 VS 2015를 사용하기 시작 그럼 난이 오류 받기 시작 :LNK2001 VS 2013 (MSVC 18)에 있지만 VS 2015 (MSVC 19)에 없습니다.

QCardManager.cpp.obj:-1: error: LNK2001: unresolved external symbol "public: static class QCard * __cdecl QCard::create(enum PLAYER,struct Question const *,enum CARD_TYPE,int const &)" ([email protected]@@[email protected]@@[email protected]@[email protected]@[email protected])

를 내가 때 나는 오류가 발생하지 않았다 VS 2013을 사용했다. 두 시간의 디버깅 후 나는 그 이유를 발견했다.

#include "2d/CCSprite.h" 
#include "CommonVariables.h" 

class RandomPostureSprite; 
class Question; 
namespace cocos2d 
{ 
class Label; 
} 

enum class CARD_TYPE { 
    QUESTION, 
    OPTION 
}; 

class QCard : public cocos2d::Sprite 
{ 
public: 
    static QCard *create(PLAYER player, const Question *question, CARD_TYPE type, const int &index); 
} 

을 그리고 QCard.cpp 파일에 그 함수의 적절한 구현을 가지고 해당 파일은 제대로 프로젝트에 추가되었습니다

여기 QCard의 거친 decleration입니다. 문제는 class Question; 전달 선언이었습니다. 나는 파일을 QCard.cpp에 포함 시켰습니다. QCard에 대한 전방 선언을 QCard.h에 사용 했으므로 QCardManager.cpp 파일에 Question에 대한 구현이 없으므로 링커 오류가 발생했습니다.

여기 내 질문이 있습니다. VS 2015는 예상되는 동작이어야한다는 것을 알고 있습니다. 그러나 왜 그런 행동이 일어나고 있습니까? 동일한 코드가 VS 2013에서는 오류없이 컴파일되지만 VS 2015에서는 컴파일되지 않습니다. Breaking Changes in Visual C++ 2015 가이드를 읽고 관련된 모든 것을 볼 수 없었습니다.

편집 1 : 는 전방 선언이 struct Question 대신 class Question 했어야 밝혀졌습니다. 을 QCardManager.cpp에 넣으려고하면 위의 링커 오류가 발생합니다. 그러나 동일한 디렉토리에있는 TimerHUD.cpp에는 없습니다. 나는 그 둘의 요약 내용을 게시 할 것이다. QCard의 선언은이 편집과 동일하게 유지됩니다. QuestionParser.h

[질문 구조체 :

struct Question { 
    Question() 
     : type() 
     , source() 
     , alias() 
     , color(0, 0, 0) 
    {} 
}; 

QCardManager.h

// Cocos2dx 
#include "math/Vec2.h" 
#include "math/CCGeometry.h" 
// Utilities 
#include "CommonVariables.h" 
// Local 
#include "GameDefinitions.h" 
#include "QuestionParser.h"// This has the Question struct 

// Forward declerations 
class QCard; 
namespace cocos2d 
{ 
class Layer; 
class Sprite; 
} 

class QCardManager 
{ 
} 

QCardManager.cpp

#include "QCardManager.h" 
// Local 
#include "QCard.h" 
#include "RandomPostureSprite.h" 
// Utilities 
#include "GameManager.h" 
#include "GameSettings.h" 
#include "CocosUtils.h" 
// Cocos2dx 
#include "cocos2d.h" 
using namespace cocos2d; 

QCardManager::QCardManager(PLAYER player, Layer &parent) 
{ 
    // This line gives the linker error 
    QCard::create(PLAYER::PLAYER_ONE, nullptr, CARD_TYPE::QUESTION, 1); 
} 

링커 오류가 발생합니다. 그러나 TimerHUD하지 않습니다. 지금 내용을 공유하고 있습니다.

TimerHUD.h

// Cocos2dx 
#include "2d/CCNode.h" 

namespace cocos2d 
{ 
class Sprite; 
class Label; 
} 

class TimerHUD : public cocos2d::Node 
{ 
} 

TimerHUD.cpp

// Cocos2dx 
#include "cocos2d.h" 
#include "SimpleAudioEngine.h" 
// Local 
#include "GameDefinitions.h" 
// Utilities 
#include "GameManager.h" 
#include "GameSettings.h" 
#include "CocosUtils.h" 
#include "QCard.h" 
using namespace cocos2d; 

TimerHUD::TimerHUD() 
{ 
    // This does not raise the linker error 
    QCard::create(PLAYER::PLAYER_ONE, nullptr, CARD_TYPE::QUESTION, 1); 
} 
+0

맞아요,'질문'은'구조체'입니다. forward 선언문을'class Question;'에서'struct Question'으로 변경 한 후에 문제가 사라집니다. 그러나 그것은 저에게 또 다른 질문을 던집니다. 변경하기 전에 오류를 발생시킨 동일한 코드가 다른 클래스에서 오류를 발생시키지 않았습니다. 내 질문에 대한 편집에 더 많은 설명을 추가했습니다. 감사. – Furkanzmc

답변

6

가 제대로 연결이에 대한 Question의 정의를 필요가 없습니다. U@[email protected]이고 링커 오류가 class Question 대신 struct Question 인 것 같습니다. 따라서 선언과 정의가 일치하지 않습니다 (Question).당신이 당신의 경고 수준을 높이한다면, 당신은 볼 줄 : 당신의 경고 수준이 너무 낮기 때문에

> type a.cpp 
struct A; 
class A {}; 

> cl /Wall a.cpp 
Microsoft (R) C/C++ Optimizing Compiler Version 19.00.24213.1 for x86 
Copyright (C) Microsoft Corporation. All rights reserved. 

a.cpp 
a.cpp(2): warning C4099: 'A': type name first seen using 'struct' now seen using 'class' 
a.cpp(2): note: see declaration of 'A' 

하지만, 그 진단을하지 않습니다.

코드는 standard's point of view에서 유효하다고 보입니다.

A declaration consisting solely of class-key identifier; is either a redeclaration of the name in the current scope or a forward declaration of the identifier as a class name. It introduces the class name into the current scope.

그러나 Visual C++의 함수 다르게 이름이 class인지에 따라의 이름을 미치게

또는 struct : C++ 11 9.1/2로부터

struct 참고 인
> undname [email protected]@[email protected]@@Z 
void __cdecl f(struct A *) 

> undname [email protected]@[email protected]@@Z 
void __cdecl f(class A *) 

것을 Uclass으로 변경되었습니다 (V). 이것은 definitely a bug in Visual C++이며 classstruct을 다르게 처리해서는 안됩니다. 이 번

은 오류가 재현 쉽고, 이해된다 :

행동이이 translation unit은 (기본적으로, .cpp)을보고 특정 여부에 의존하기 때문에
> type a.cpp 
class A;   // declares A as a class 
void f(A* a);  // declares f(class A*) 

int main() 
{ 
    f(nullptr); // calls f(class A*) 
} 


> type b.cpp 
struct A {};  // defines A as a struct, mismatch! 
void f(A* a) {} // defines f(struct A*)! 


> cl /nologo a.cpp b.cpp 
a.cpp 
b.cpp 
Generating Code... 
a.obj : error LNK2019: unresolved external symbol 
    "void __cdecl f(class A *)" ([email protected]@[email protected]@@Z) referenced 
     in function _main 
a.exe : fatal error LNK1120: 1 unresolved externals 

그래서 당신이 이상한 문제가 발생하는 이유는 Questionclass 또는 struct으로 지정하십시오. 이것은 차례대로 어떤 헤더가 포함되어 있는가에 달려 있습니다.

서로 다른 번역 단위로 일치하지 않아야합니다. 동일한 단위, Visual C++ will use the the class-key from the definition 내에서 서로 다른 선언을하기 전에가있는 경우에도이 비주얼 C++ 2013에서 문제가 아니었다 이유에 관해서는

Compiler Warning (level 2) C4099

'identifier' : type name first seen using 'objecttype1' now seen using 'objecttype2'

An object declared as a structure is defined as a class, or an object declared as a class is defined as a structure. The compiler uses the type given in the definition.

, 나는 맹 글링 방식은 최근에 변경된 것을 의심한다. 이 버그가있는 것 같습니다. since at least 6.0. 포함 된 순서를 실수로 변경했을 수 있습니다.