Search code examples
.net.net-2.0polymorphismmanaged-c++

Unresolved Token in Managed C++


I have a mystery on my hands. I am trying to learn managed C++ coming from a C# background and have run into a snag. If I have a project which includes two classes, a base class Soup and a derived class TomatoSoup which I compile as a static library (.lib), I get unresolved tokens on the virtual methods in Soup. Here is the code:


Abstracts.proj

Soup.h

namespace Abstracts
{
    public ref class Soup abstract
    {
    public:
        virtual void heat(int Degrees);
    };
}

TomatoSoup.h

#include "Soup.h"

namespace Abstracts
{
    public ref class TomatoSoup : Abstracts::Soup
    {
    public:
        virtual void heat(int Degrees) override;
    };
}

TomatoSoup.cpp

#include "TomatoSoup.h"

void Abstracts::TomatoSoup::heat(int Degrees)
{
    System::Console::WriteLine("Soup's on.");
}

Main.proj

Main.cpp

#include "TomatoSoup.h"

using namespace System;

int main(array<System::String ^> ^args)
{
    Abstracts::TomatoSoup^ ts = gcnew Abstracts::TomatoSoup();

    return 0;
}

I get this link-time error on Main.proj:

1>Main.obj : error LNK2020: unresolved token (06000001) Abstracts.Soup::heat
  1. I've tried setting

    virtual void heat(int Degrees)=0;
    
  2. I've tried implementing heat in the base class

    virtual void heat(int Degrees){} 
    

    and get an unreferenced formal parameter warning treated as an error.

  3. I've tried both 1 and 2 with and without the abstract keyword on the Soup class

This issue is driving me crazy and I hope to prevent it from driving other developers nuts in the future.

UPDATE: This worked with Greg Hewgill's argument-name commenting method when the TomatoSoup::heat was implemented in the header file, but the error came back when I moved the implementation to TomatoSoup.cpp. I've modified the question to reflect that.


Solution

  • The error you are getting (LNK2020) means the linker can't find a definition for the Abstracts.Soup::heat function anywhere. When you declare the function as virtual void heat(int Degrees); the linker will expect to find the function body defined somewhere.

    If you intend not to supply a function body, and require that subclasses eventually override the function, you should do as you indicated in solution 1:

    virtual void heat(int Degrees) = 0;
    

    This tells the compiler that you aren't going to implement the function. What happens when you do that?

    Also, with reference to your second solution:

    virtual void heat(int Degrees) {}
    

    the compiler is telling you that you don't reference the Degrees parameter within the function. One way to avoid this warning in C++ is to not give the parameter a name:

    virtual void heat(int /*Degrees*/) {}
    

    Supplying an empty implementation is a bit different from a pure virtual (= 0) declaration, though.