2016-08-17 7 views
3

以前のバージョンのCocos2dxを使ってゲームを作成し、VS 2013でコンパイルしていました.Makeと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を使用しています。数時間のデバッグ後、私はその理由を知りました。

はここQCardのラフdeclerationです:

#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ファイルにその関数の適切な実施を持っていたし、そのファイルも適切にプロジェクトに追加されました。 したがって、問題はclass Question;前方宣言でした。私はQuestionParser.hファイルをQCard.cppに含めましたが、QCardの順方向宣言をQCard.hに使用したので、QCardManager.cppファイルにはQuestionの実装がなく、リンカーエラーが発生しました。

ここに私の質問があります:VS 2015が期待する動作であるはずです。しかし、なぜその行動が起こっているのですか?同じコードがVS 2013ではエラーなしでコンパイルされますが、VS 2015ではコンパイルされません。私はBreaking Changes in Visual C++ 2015のガイドを読んで、関連するものは何も表示されませんでした。

EDIT 1: 前方宣言がstruct Question代わりのclass Questionされている必要がありますが判明。私がをQCardManager.cppに使用しようとすると、上記のリンカエラーが発生します。しかし、同じディレクトリにあるTimerHUD.cppにはありません。私はその両方の要約内容を投稿します。 QCardの宣言をこの編集と同じにしておきます。

QuestionParser.hにある質問構造体、:

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

QCardManagerがリンカエラーを発生させます。しかし、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

あなたが正しいです、 'Question'は' struct'です。前方宣言を '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から有効です。 C++ 11 9.1/2から:

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++は名前がclassstructであるかに応じて、異なる機能の名前を狂わせる:structであることを

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

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

注意UおよびclassとしてVと表示されます。これはdefinitely a bug in Visual C++です。classstructを別々に扱うべきではありません。

これが理解されたら、エラーが再現するのは簡単です:

> 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 

行動が特定のtranslation unit(基本的には、.cppは)見ているかどうかに依存しているため、あなたはこれらの奇妙な問題を抱えている理由は、 Questionclassまたはstructとしてください。これは、どのヘッダーが含まれているかによって異なります。

異なる翻訳単位にするには、不一致が必要であることに注意してください。同じユニット、Visual C++ will use the the class-key from the definitionの中で、さまざまな宣言が前にある場合でも:これは、Visual 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インクルードの順序を誤って変更した可能性があります。

関連する問題