用作默认参数的静态成员导致无法解析的外部

kri*_*_sw 2 c++

我有一个使用静态成员变量作为默认参数的令人困惑的问题。由于相同的语言构造在不同的地方工作,它可能与项目 (DLL) 的相互依赖关系有关。所以如果我的例子太复杂,请接受我的歉意,但我应该画出整个画面,因为我不知道出了什么问题。

我有一个基类(代表一种错误代码)

错误库文件

class ErrorBase
{
public:
    typedef unsigned long ErrorCode;

    /// here go the error codes. For reasons I do not want to explain, I cannot use an enumeration here.
    static const ErrorCode ERROR_UNINITIALIZED;
    static const ErrorCode ERROR_OK;
    ///...and so on

    ErrorBase(ErrorCode theCode = ERROR_UNINITIALIZED);
};
Run Code Online (Sandbox Code Playgroud)

...在ErrorBase.cpp 中,我正在为代码赋值......

const ErrorBase::ErrorCode ErrorBase::ERROR_UNINITIALIZED = 0xffffffff;
const ErrorBase::ErrorCode ErrorBase::ERROR_OK = 0x0;
//.. and so on...
Run Code Online (Sandbox Code Playgroud)

ErrorBase 从一个 DLL 导出,该 DLL 为我们的项目提供了一些通用类

现在我正在为更具体的错误派生另一个错误类,它具有特定于特定类型错误的附加属性。类SpecificError 是不同DLL 的一部分,该DLL 链接到包含ErrorBase 的通用DLL。我没有包含 dllimport/dllexport shebang,但是我们到处都在使用它,并且它适用于所有情况。如果您有疑问,我可以编辑我的代码示例。

特定错误.h

class SpecificError : public ErrorBase
{
    public:
       static const ErrorCode SPECIFIC_ERROR_UNINITIALIZED;
       static const ErrorCode SPECIFIC_ERROR_SOMETHING_WENT_WRONG;

       SpecificError(ErrorCode theCode = SPECIFIC_ERROR_UNINITIALIZED);
};
Run Code Online (Sandbox Code Playgroud)

...在SpecificError.cpp中,我定义了这些值:

const SpecificError::ErrorCode SpecificError::SPECIFIC_ERROR_UNINITIALIZED = ErrorBase::ERROR_UNINITIALIZED;
Run Code Online (Sandbox Code Playgroud)

与 ErrorBase 一样,SpecificError 是从处理特定功能的 DLL 导出的。请注意,两个错误类都使用“UNINITIALIZED”值作为错误代码的默认值声明了一个构造函数。

现在我有一个依赖于两个 DLL 的程序,因此通过相应的导入库链接到它们。该程序包括ErrorBase.h 和SpecificError.h。ErrorCode.h 似乎没有任何问题,但是关于 SpecificError.h 我收到了

LNK2001 未解析的外部符号 SpecificError::ErrorCode SpecificError::SPECIFIC_ERROR_UNINITIALIZED 在 main.obj 中引用。

(备注:main.cpp 没有明确使用SpecificError,它只包含头文件)。

我能够通过从 SpecificError 构造函数中删除默认参数并声明一个默认构造函数来解决这个问题,该构造函数在其实现中调用 ErrorBase 的继承构造函数,并将 SPECIFIC_ERROR_UNINITIALIZED 传递给它。这使我假设符号 SPECIFIC_ERROR_UNINITIALIZED正确声明和定义,但不能用作参数默认值。但是,这似乎仅适用于特定错误,在 ErrorBase 中一切似乎都很好。

工具集:我使用 Visual C++ 2017 作为编译器。

bhr*_*tov 6

我重新创建了链接错误。对您的文件进行以下更改,根据您上面显示的代码片段,它应该可以正常工作:SpecificError.cpp

// I sent theCode to the Base class
SpecificError::SpecificError(ErrorCode theCode) : ErrorBase(theCode)
{
// ...
}
Run Code Online (Sandbox Code Playgroud)

在 ErrorBase.cpp 中,我刚刚添加了构造函数,但您可能已经有了这个:

ErrorBase::ErrorBase(ErrorCode theCode) 
{ 
// ...
}
Run Code Online (Sandbox Code Playgroud)

完成此操作后,我还必须将静态常量的初始化从 .cpp 文件移至 .h。然后我通过执行以下操作来测试代码:

    SpecificError e; // theCode ends up being 0xffffffff
    SpecificError e1(20); // theCode ends up being 20
Run Code Online (Sandbox Code Playgroud)

我希望这对你有帮助。

这是我的 ErrorBase.cpp 的样子:

#pragma once
#include"ErrorBase.h"
#include<iostream>

ErrorBase::ErrorBase(ErrorCode theCode) {
    std::cout << theCode << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

错误库.h:

#pragma once
class ErrorBase
{
public:
    typedef unsigned long ErrorCode;

    static const ErrorCode ERROR_UNINITIALIZED = 0xffffffff;
    static const ErrorCode ERROR_OK = 0x0;

    ErrorBase(const ErrorCode = ERROR_UNINITIALIZED);
};
Run Code Online (Sandbox Code Playgroud)

具体Error.cpp:

#pragma once
#include"SpecificError.h" 

SpecificError::SpecificError(ErrorCode theCode) : ErrorBase(theCode)
{

}

Run Code Online (Sandbox Code Playgroud)

具体错误.h:

#pragma once
#include "ErrorBase.h"
class SpecificError : public ErrorBase
{
public:
    static const ErrorCode SPECIFIC_ERROR_UNINITIALIZED = ErrorBase::ERROR_UNINITIALIZED;
    static const ErrorCode SPECIFIC_ERROR_SOMETHING_WENT_WRONG = -42;

    SpecificError(ErrorCode theCode = SPECIFIC_ERROR_UNINITIALIZED);
};
Run Code Online (Sandbox Code Playgroud)