奇怪的未解决的外部错误

时间:2011-10-01 23:02:00

标签: c++ winapi gdi unresolved-external

我遇到了一些未解决的外部错误我似乎无法找到解决方案:

1>MyApp.obj : error LNK2019: unresolved external symbol "public: void __thiscall Path::AddPoint(struct Point2D const &)" (?AddPoint@Path@@QAEXABUPoint2D@@@Z) referenced in function "public: static long __stdcall MyApp::WndProc(struct HWND__ *,unsigned int,unsigned int,long)" (?WndProc@MyApp@@SGJPAUHWND__@@IIJ@Z)
1>MyApp.obj : error LNK2019: unresolved external symbol "public: void __thiscall Path::ClrPath(void)" (?ClrPath@Path@@QAEXXZ) referenced in function "public: static long __stdcall MyApp::WndProc(struct HWND__ *,unsigned int,unsigned int,long)" (?WndProc@MyApp@@SGJPAUHWND__@@IIJ@Z)
1>MyApp.obj : error LNK2019: unresolved external symbol "public: enum TOOL __thiscall Path::GetTool(void)" (?GetTool@Path@@QAE?AW4TOOL@@XZ) referenced in function "public: static long __stdcall MyApp::WndProc(struct HWND__ *,unsigned int,unsigned int,long)" (?WndProc@MyApp@@SGJPAUHWND__@@IIJ@Z)
1>MyApp.obj : error LNK2019: unresolved external symbol "public: void __thiscall Path::SetTool(enum TOOL)" (?SetTool@Path@@QAEXW4TOOL@@@Z) referenced in function "public: static long __stdcall MyApp::WndProc(struct HWND__ *,unsigned int,unsigned int,long)" (?WndProc@MyApp@@SGJPAUHWND__@@IIJ@Z)

奇怪的是,我很确定我正确地包含了一切。此外,总有一个函数适用于该类:DrawTo()。

我尝试删除其他功能的“内联”声明,但似乎并不重要。

我还尝试重建一次,只需在两个函数之间添加一些额外的结束,然后编译!下次我尝试编译它时不再起作用......

所以我不完全确定我做错了什么,或者它是否是编译器...(默认VS2010编译器)(实际上,该编译器的名称是什么?[注释或编辑])

有谁知道这可能意味着什么?

以下是相关代码:(如果您需要查看更多,评论和我将编辑)


Path.h

#pragma once
#ifndef PATH_H
#define PATH_H

#include "Defines.h"
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>

#include "MyVector.h"

#include "Point2D.h"
#include "Tool.h"

class Path
{
public:
    Path();
    virtual ~Path();

    bool DrawTo(HDC hDC);

    inline void AddPoint(const Point2D& rkPoint);
    inline Point2D GetPointAt(int iIndex) const;
    inline int GetPointCount() const;

    inline TOOL GetTool();
    inline void SetTool(TOOL t);
    inline void SetColor1(COLORREF);
    inline void SetColor2(COLORREF);

    inline void ClrPath();

private:
    MyVector<Point2D> m_PointVector;
    TOOL m_Tool;

    COLORREF m_Colour1;
    COLORREF m_Colour2;
};

#endif

Path.cpp

#include "Path.h"

Path::Path()
{
    m_Tool = Tool_Pen;

    m_Colour1 = RGB(0,0,0);
    m_Colour2 = RGB(255,255,255);
}

Path::~Path()
{}

bool Path::DrawTo(HDC hDC)
{
    if(hDC == NULL || m_PointVector.GetLength() <= 0) {
        return false;
    }

    switch (m_Tool) {
    case Tool_Pen:
        {
            //////
            break;
        }
    case Tool_Line:
        {
            /////
            break;
        }
    case Tool_Ellipse:
        {
            //////
            break;
        }
    case Tool_Rectangle:
        {
            //////
            break;
        }
    case Tool_LineTrack:
        {
            //////
            break;
        }
    }

    return true;
}

Point2D Path::GetPointAt(int iIndex) const {
    return m_PointVector.At(iIndex);
}

int Path::GetPointCount() const {
    return m_PointVector.GetLength();
}

void Path::AddPoint(const Point2D& rkPoint) {
    m_PointVector.PushBack(rkPoint);
}

TOOL Path::GetTool() {
    return m_Tool;
}

void Path::SetTool(TOOL t) {
    m_Tool = t;
}

void Path::SetColor1(COLORREF col) {
    m_Colour1 = col;
}

void Path::SetColor2(COLORREF col) {
    m_Colour2 = col;
}

void Path::ClrPath() {
    m_PointVector.ClrAll();
}

MyApp.h

#pragma once
#ifndef MYAPP_H
#define MYAPP_H

#include "Defines.h"
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <string>
#include <iostream>

//app includes:
#include "MyHelperFuncs_Win32.h"
#include "BitmapPainter.h"
#include "Path.h"
//-------------

class MyApp 
{
public:
    MyApp();
    virtual ~MyApp();
    static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    void Paint();

private:
    void InitWindows();

    HWND m_hWnd;
    HDC m_hDC;
    PAINTSTRUCT m_PaintStruct;

    //app-specific:
    BitmapPainter* m_pBitmapPainter;
    Path* m_pPath;
    //------------
};

#endif

MyApp的:: WndProc()中

LRESULT MyApp::WndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
    if(iMsg == WM_CREATE)
    {
        CREATESTRUCT *pCS = (CREATESTRUCT*)lParam;
        SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG)pCS->lpCreateParams);
    }
    else
    {
        //retrieve the stored "this" pointer
        MyApp* pApp = (MyApp*)GetWindowLongPtr(hWnd, GWLP_USERDATA);

        switch (iMsg)
        {
            case WM_PAINT:
                {
                pApp->Paint();
                return 0;
                }

            case WM_COMMAND:
            {
                int wmId    = LOWORD(wParam);
                int wmEvent = HIWORD(wParam);

                // Parse the menu selections:
                switch (wmId)
                {
                case IDM_NEW:
                    {
                    //////
                    return 0;
                case IDM_LOAD:
                    {
                    //////
                    return 0;
                    }
                case IDM_SAVE:
                    {
                    //////
                    return 0;
                    }
                case IDM_SAVEAS:
                    {
                    //////
                    return 0;
                    }
                case IDM_EXIT:
                    {
                    DestroyWindow(hWnd);
                    return 0;
                    }
                case IDM_COLOURMAIN:
                    {
                    //////
                    return 0;
                    }
                case IDM_COLOURSECONDARY:
                    {
                    //////
                    return 0;
                    }
                case IDM_PEN:
                    {
                        pApp->m_pPath->SetTool(Tool_Pen);
                        return 0;
                    }
                case IDM_LINE:
                    {
                        pApp->m_pPath->SetTool(Tool_Line);
                        return 0;
                    }
                case IDM_ELLIPSE:
                    {
                        pApp->m_pPath->SetTool(Tool_Ellipse);
                        return 0;
                    }
                case IDM_RECTANGLE:
                    {
                        pApp->m_pPath->SetTool(Tool_Rectangle);
                        return 0;
                    }
                case IDM_LINETRACK:
                    {
                        pApp->m_pPath->SetTool(Tool_LineTrack);
                        return 0;
                    }
                default:
                    {
                    //////
                    return 0;
                    }
                }
            }

            case WM_LBUTTONUP:
                {
                    OutputDebugString(_T("Left Button Up\n "));
                    if(wParam & MK_CONTROL)OutputDebugString(_T("The CTRL key is down.\n "));
                    int x = LOWORD(lParam);
                    int y = HIWORD(lParam);

                    switch(pApp->m_pPath->GetTool()) {
                        case Tool_Pen:
                            {
                            pApp->m_pPath->DrawTo(pApp->m_hDC);
                            pApp->m_pPath->ClrPath();
                            InvalidateRect(pApp->m_hWnd,NULL,true);
                            }
                    }

                    return 0;
                }

            case WM_LBUTTONDOWN:
                {
                    OutputDebugString(_T("Left Button Down\n "));
                    if(wParam & MK_CONTROL)OutputDebugString(_T("The CTRL key is down.\n "));
                    int x = LOWORD(lParam);
                    int y = HIWORD(lParam);

                    return 0;
                }

            case WM_RBUTTONUP:
                {
                    OutputDebugString(_T("Right Button Up\n "));
                    if(wParam & MK_CONTROL)OutputDebugString(_T("The CTRL key is down.\n "));
                    int x = LOWORD(lParam);
                    int y = HIWORD(lParam);

                    return 0;
                }
            case WM_MOUSEMOVE:
                {
                    OutputDebugString(_T("Mouse Moved\n "));
                    if(wParam & MK_CONTROL)OutputDebugString(_T("The CTRL key is down.\n "));
                    int x = LOWORD(lParam);
                    int y = HIWORD(lParam);
                    std::cout <<"Mouse Position: x="  << x << " y=" << y << "\n";

                    if (wParam & MK_LBUTTON) {
                        switch(pApp->m_pPath->GetTool()) {
                        case Tool_Pen:
                            {
                            Point2D p;
                            p.x = x;
                            p.y = y;
                            pApp->m_pPath->AddPoint(p);
                            InvalidateRect(pApp->m_hWnd,NULL,true);
                            }
                        }
                    }

                    return 0;
                }

            case WM_DESTROY:
                {
                PostQuitMessage(0);
                return 0;
                }
        }
    }
    return DefWindowProc (hWnd, iMsg, wParam, lParam) ;
}

2 个答案:

答案 0 :(得分:3)

取出那些“内联”声明(因为代码没有内联,除非它实际上在头文件中)。然后做一个干净的构建,然后完整构建。

答案 1 :(得分:2)

唯一有效的功能是没有内联的功能。

如果你仔细想想,你会意识到它是有道理的。当编译器正在编译MyApp.cpp时,它发现您正在调用声明为inline的方法。因此编译器需要复制该方法的代码而不是仅仅调用它。问题是,编译器如何知道定义该方法的位置?编译器可以看到的唯一方法是内联方法的实现是在Path.h中还是在MyApp.cpp包含的其他头文件中。

因此,最简单的解决方案是将所有这些内联方法的实现移动到Path.h文件中。