LNK2019未解析的带静态函数的符号

时间:2015-05-23 07:31:14

标签: c++

我不明白为什么以下代码会产生未解析的符号

main.cpp中:

#include <Windows.h>
#include "rendermanager.h"
#include "gamestatemanager.h"

using namespace GameplayLib;
using namespace RenderLib;

//Window Procedure Methods
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT paint_struct;
    HDC hDC;

    switch (message)
    {
    case WM_PAINT:
        hDC = BeginPaint(hwnd, &paint_struct);
        EndPaint(hwnd, &paint_struct);
        break;

    case WM_DESTROY:
        PostQuitMessage(0);
        break;

    default:
        return DefWindowProc(hwnd, message, wParam, lParam);
    }

    return 0;
}

int WINAPI wWinMain(HINSTANCE h_instance, HINSTANCE prev_instance, LPWSTR cmd_line, int cmd_show)
{
    //Suppress unused warning for these parameters
    UNREFERENCED_PARAMETER(prev_instance);
    UNREFERENCED_PARAMETER(cmd_line);

    //Initialize a window
    WNDCLASSEX wnd_class = { 0 };
    wnd_class.cbSize = sizeof(WNDCLASSEX);
    wnd_class.style = CS_HREDRAW | CS_VREDRAW;
    wnd_class.lpfnWndProc = WndProc;    //Callback function that's called whenever an event notification comes form OS.
    wnd_class.hInstance = h_instance;
    wnd_class.hCursor = LoadCursor(NULL, IDC_ARROW);
    wnd_class.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wnd_class.lpszMenuName = NULL;
    wnd_class.lpszClassName = "ProjectX";

    if (RegisterClassEx(&wnd_class) == false)
    {
        return -1;
    }

    RECT window_rect = { 0, 0, 800, 600 };
    AdjustWindowRect(&window_rect, WS_OVERLAPPEDWINDOW, FALSE);

    HWND hwnd = CreateWindowA("ProjectX", "ProjectX 0.01", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, window_rect.right - window_rect.left, window_rect.bottom - window_rect.top, NULL, NULL, h_instance, NULL);
    if (hwnd == NULL)
    {
        return -1;
    }

    ShowWindow(hwnd, cmd_show);

    //Initialize sub-systems
    cGameStateManager::Create();
    cRenderManager::Create(h_instance, hwnd);

    //Enter Main loop
    MSG msg = { 0 };
    while (true)
    {
        while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            //translate keystroke msgs into the right format
            TranslateMessage(&msg);
            //Send the msg to WndProc
            DispatchMessage(&msg);
        }
        if (msg.message == WM_QUIT)
        {
            //Shutdown
            cRenderManager::Destroy();
            cGameStateManager::Destroy();
            break;
        }
        else
        {
            //Update
            cGameStateManager::Instance().Update();
            //Render
            cRenderManager::Instance().Render();
        }
    }
    return static_cast<int>(msg.wParam);

}

gamestatemanager.h:

#pragma once

namespace GameplayLib
{
    class cGameStateManager
    {
    public:
        static void Create();
        static void Destroy();
        static cGameStateManager& Instance();

        void Update();

    private:
        explicit cGameStateManager();
        ~cGameStateManager();

        static cGameStateManager* sGameStateManagerInstance;
    };

}

gamestatemanager.cpp:

#include "gamestatemanager.h"

using namespace GameplayLib;

cGameStateManager*  cGameStateManager::sGameStateManagerInstance = nullptr;

//static 
void cGameStateManager::Create()
{
    sGameStateManagerInstance = new cGameStateManager();
}

//static 
void cGameStateManager::Destroy()
{
    delete sGameStateManagerInstance;
}

//static 
cGameStateManager& cGameStateManager::Instance()
{
    return *sGameStateManagerInstance;
}

void cGameStateManager::Update()
{

}

//Private
cGameStateManager::cGameStateManager()
{

}

cGameStateManager::~cGameStateManager()
{

}

奇怪的是,cRenderManager遵循完全相同的单例模式但没有未解析的符号。它在main.cpp中没有cGameStateManager代码编译得很好。这是源代码。

rendermanager.h:

#pragma once

#include "directxincludes.h"

namespace RenderLib
{

    class cRenderManager
    {
    public:
        static void Create(HINSTANCE h_instance, HWND hwnd);
        static void Destroy();
        static cRenderManager& Instance();

        void Render();

    private:
        explicit cRenderManager();
        ~cRenderManager();

        static cRenderManager* sRenderManagerInstance;  //Static instance

        HINSTANCE mHInstance;                       //Handle to instance
        HWND mHWND;                                 //Handle to window
        D3D_DRIVER_TYPE mD3DDriverType;             //Device type
        D3D_FEATURE_LEVEL mD3DFeatureLevel;         //Feature level
        ID3D11Device* mD3DDevice;                   //Device
        ID3D11DeviceContext* mD3DDeviceContext;     //Device context
        IDXGISwapChain* mDXGISwapChain;             //Swap chain
        ID3D11RenderTargetView* mRenderTargetView;  //Back buffer

    };

}

rendermanager.cpp:

#include "rendermanager.h"

using namespace RenderLib;

cRenderManager* cRenderManager::sRenderManagerInstance = nullptr;

//static
void cRenderManager::Create(HINSTANCE h_instance, HWND hwnd)
{
    sRenderManagerInstance = new cRenderManager();
    sRenderManagerInstance->mHInstance = h_instance;
    sRenderManagerInstance->mHWND = hwnd;
    //Get the dimensions
    RECT dimensions;
    GetClientRect(hwnd, &dimensions);
    unsigned int width = dimensions.right - dimensions.left;
    unsigned int height = dimensions.bottom - dimensions.top;
    //D3D driver types
    D3D_DRIVER_TYPE driver_types[] = 
    {
        D3D_DRIVER_TYPE_HARDWARE, 
        D3D_DRIVER_TYPE_WARP,
        D3D_DRIVER_TYPE_SOFTWARE
    };
    unsigned int total_driver_types = ARRAYSIZE(driver_types);
    //D3D feature levels in the order we support
    D3D_FEATURE_LEVEL feature_levels[] = 
    {
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_10_1,
        D3D_FEATURE_LEVEL_10_0
    };
    unsigned int total_feature_levels = ARRAYSIZE(feature_levels);
    //Create swap chain
    DXGI_SWAP_CHAIN_DESC swap_chain_desc;
    ZeroMemory(&swap_chain_desc, sizeof(swap_chain_desc));
    swap_chain_desc.BufferCount = 1;
    swap_chain_desc.BufferDesc.Width = width;
    swap_chain_desc.BufferDesc.Height = height;
    swap_chain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    swap_chain_desc.BufferDesc.RefreshRate.Numerator = 60;
    swap_chain_desc.BufferDesc.RefreshRate.Denominator = 1;
    swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    swap_chain_desc.OutputWindow = hwnd;
    swap_chain_desc.Windowed = true;
    swap_chain_desc.SampleDesc.Count = 1;
    swap_chain_desc.SampleDesc.Quality = 0;
    unsigned int creation_flags = 0;
#ifdef _DEBUG
    creation_flags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
    //Create driver
    HRESULT result;
    unsigned int driver = 0;
    for (driver = 0; driver < total_driver_types; ++driver)
    {
        result = D3D11CreateDeviceAndSwapChain(0, driver_types[driver], 0, creation_flags, feature_levels, total_feature_levels, D3D11_SDK_VERSION,
            &swap_chain_desc, &sRenderManagerInstance->mDXGISwapChain, &sRenderManagerInstance->mD3DDevice,
            &sRenderManagerInstance->mD3DFeatureLevel, &sRenderManagerInstance->mD3DDeviceContext);

        if (SUCCEEDED(result))
        {
            sRenderManagerInstance->mD3DDriverType = driver_types[driver];
            break;
        }
    }
    if (FAILED(result))
    {
        DXTRACE_MSG("Failed to create the Direct3D Device!");
        //TODO handle this?
        return;
    }
    //Create back buffer texture
    ID3D11Texture2D* backbuffer_texture = nullptr;
    result = sRenderManagerInstance->mDXGISwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&backbuffer_texture);
    if (FAILED(result))
    {
        DXTRACE_MSG("Failed to get the swap chain back buffer!");
        //TODO handle this?
        return;
    }
    //Create the render target view
    result = sRenderManagerInstance->mD3DDevice->CreateRenderTargetView(backbuffer_texture, 0, &sRenderManagerInstance->mRenderTargetView);
    if (backbuffer_texture != nullptr)
    {
        backbuffer_texture->Release();
    }
    if (FAILED(result))
    {
        DXTRACE_MSG("Failed to create the render target view!");
        //TODO handle this?
        return;
    }
    //Setup render target
    sRenderManagerInstance->mD3DDeviceContext->OMSetRenderTargets(1, &sRenderManagerInstance->mRenderTargetView, 0);
    //Setup viewport
    D3D11_VIEWPORT viewport;
    viewport.Width = static_cast<float>(width);
    viewport.Height = static_cast<float>(height);
    viewport.MinDepth = 0.0f;
    viewport.MaxDepth = 1.0f;
    viewport.TopLeftX = 0.0f;
    viewport.TopLeftY = 0.0f;
    sRenderManagerInstance->mD3DDeviceContext->RSSetViewports(1, &viewport);
}

//static
void cRenderManager::Destroy()
{
    if (sRenderManagerInstance->mRenderTargetView != nullptr)
    {
        sRenderManagerInstance->mRenderTargetView->Release();
    }
    if (sRenderManagerInstance->mDXGISwapChain != nullptr)
    {
        sRenderManagerInstance->mDXGISwapChain->Release();
    }
    if (sRenderManagerInstance->mD3DDeviceContext != nullptr)
    {
        sRenderManagerInstance->mD3DDeviceContext->Release();
    }
    if (sRenderManagerInstance->mD3DDevice != nullptr)
    {
        sRenderManagerInstance->mD3DDevice->Release();
    }
    sRenderManagerInstance->mD3DDevice = nullptr;
    sRenderManagerInstance->mD3DDeviceContext = nullptr;
    sRenderManagerInstance->mDXGISwapChain = nullptr;
    sRenderManagerInstance->mRenderTargetView = nullptr;

    delete sRenderManagerInstance;
}

//static
cRenderManager& cRenderManager::Instance()
{
    return *sRenderManagerInstance;
}

void cRenderManager::Render()
{
    //Render all your stuff!
}

//Private
cRenderManager::cRenderManager()
    : mD3DDriverType( D3D_DRIVER_TYPE_NULL )
    , mD3DFeatureLevel( D3D_FEATURE_LEVEL_11_0 )
    , mD3DDevice( nullptr )
    , mD3DDeviceContext( nullptr )
    , mDXGISwapChain( nullptr )
    , mRenderTargetView( nullptr )
{

}

cRenderManager::~cRenderManager()
{
    //Private destructor. Do nothing
}

最后,我收到以下编译错误:

1>  gamestatemanager.h
1>  gamestatemanager.cpp
1>  Generating Code...
1>x64\Debug\//gamestatemanager.obj : warning LNK4042: object specified more than once; extras ignored
1>main.obj : error LNK2019: unresolved external symbol "public: static void __cdecl GameplayLib::cGameStateManager::Create(void)" (?Create@cGameStateManager@GameplayLib@@SAXXZ) referenced in function wWinMain
1>main.obj : error LNK2019: unresolved external symbol "public: static void __cdecl GameplayLib::cGameStateManager::Destroy(void)" (?Destroy@cGameStateManager@GameplayLib@@SAXXZ) referenced in function wWinMain
1>main.obj : error LNK2019: unresolved external symbol "public: static class GameplayLib::cGameStateManager & __cdecl GameplayLib::cGameStateManager::Instance(void)" (?Instance@cGameStateManager@GameplayLib@@SAAEAV12@XZ) referenced in function wWinMain
1>main.obj : error LNK2019: unresolved external symbol "public: void __cdecl GameplayLib::cGameStateManager::Update(void)" (?Update@cGameStateManager@GameplayLib@@QEAAXXZ) referenced in function wWinMain
1>G:\Programming\C++\Projects\ProjectX\x64\Debug\ProjectX.exe : fatal error LNK1120: 4 unresolved externals

0 个答案:

没有答案