1

I'm getting some Unresolved External Errors I can't seem to find a solution for:

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)

The weird thing is, I'm pretty sure I included everything correctly. Also, there's always one function that works of that class: DrawTo().

I tried to remove the 'inline' declaration for the other functions but it didn't seem to matter.

I also tried to rebuild it once, with just putting some extra endline in between two functions, and it compiled! Next time I tried compiling it didn't work again...

So I'm not entirely sure if I'm doing something wrong, or if it's the compiler... (Default VS2010 compiler) (actually, what's the name of that compiler? [comment or edit] )

Does anyone know what this could mean?

Here's the relevant code: (if you need to see more, comment and I'll edit)


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

2 回答 2

3

Take out those "inline" declarations (because code isn't inlined unless it's actually in the header file). And then do a clean build followed by a full build.

于 2011-10-01T23:14:58.317 回答
2

The only function that works is the one that is not inlined.

If you think about it you'll realize it makes sense. When the compiler is compiling MyApp.cpp it finds that you are calling a method declared as inline. So the compiler needs to copy the code for that method instead of just calling it. The problem is, how does the compiler know where that method is defined? The only way the compiler can see it is if it the implementation of the inline methods is either in Path.h or in some other header file that is included by MyApp.cpp.

So the simplest solution is for you to move the implementation of all those inline methods into the Path.h file.

于 2011-10-01T23:22:20.043 回答