3

我手上有一个谜。我正在尝试学习来自 C# 背景的托管 C++,但遇到了障碍。如果我的项目包含两个类,一个基类Soup和一个派生类TomatoSoup,我将其编译为静态库 (.lib),我会在Soup中的虚拟方法上获得未解析的标记。这是代码:


Abstracts.proj

汤.h

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

番茄汤.h

#include "Soup.h"

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

番茄汤.cpp

#include "TomatoSoup.h"

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

主项目

主文件

#include "TomatoSoup.h"

using namespace System;

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

    return 0;
}

我在Main.proj上收到此链接时错误:

1>Main.obj : error LNK2020: unresolved token (06000001) Abstracts.Soup::heat
  1. 我试过设置

    virtual void heat(int Degrees)=0;
    
  2. 我尝试在基类中实现热量

    virtual void heat(int Degrees){} 
    

    并将未引用的形式参数警告视为错误。

  3. 我已经在 Soup 类上尝试了 1 和 2 有和没有 abstract 关键字

这个问题让我发疯了,我希望能防止它在未来让其他开发人员发疯。

更新:当在头文件中实现 TomatoSoup::heat 时,这与 Greg Hewgill 的参数名称注释方法一起使用,但是当我将实现移动到 TomatoSoup.cpp 时错误又回来了。我已经修改了问题以反映这一点。

4

3 回答 3

3

您收到的错误(LNK2020)意味着链接器无法在Abstracts.Soup::heat任何地方找到该函数的定义。当您将函数声明为virtual void heat(int Degrees);链接器时,将期望在某处找到定义的函数体。

如果您不打算提供函数体,并要求子类最终覆盖该函数,则应按照解决方案 1 中的指示进行操作:

virtual void heat(int Degrees) = 0;

这告诉编译器你不会实现这个函数。当你这样做时会发生什么?

另外,参考您的第二个解决方案:

virtual void heat(int Degrees) {}

编译器告诉您您没有在函数中引用 Degrees 参数。在 C++ 中避免此警告的一种方法是不给参数命名:

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

= 0不过,提供一个空实现与纯 virtual ( ) 声明有点不同。

于 2008-12-10T18:01:43.310 回答
2

我认为这个错误可能是因为我试图将 Abstracts.proj 构建为静态库。当我将其更改为 .DLL 时,一切正常。

我已经看到静态库不支持托管代码,但没有任何官方支持。有没有人有一个很好的参考说明这一点?

于 2008-12-10T23:21:45.320 回答
0

我没有太多 CLI 经验,但我认为您应该使用 public 继承:

公共参考类番茄汤:公共摘要::汤

于 2008-12-10T18:15:14.813 回答