gpt4 book ai didi

c++ - 如何在命名空间中正确使用 extern?

转载 作者:太空狗 更新时间:2023-10-29 22:53:31 27 4
gpt4 key购买 nike

我正在努力让 rLog 在 Windows 下构建为 DLL,但我遇到了与 rlog 命名空间中的某些全局符号相关的 undefined symbol 错误。特别是 RLogChannel.cpp 中的这些:

namespace rlog {
...
RLogChannel *_RLDebugChannel = GetGlobalChannel( "debug", Log_Debug );
RLogChannel *_RLInfoChannel = GetGlobalChannel( "info", Log_Info );
RLogChannel *_RLWarningChannel = GetGlobalChannel( "warning", Log_Warning );
RLogChannel *_RLErrorChannel = GetGlobalChannel( "error", Log_Error );
...
};

我认为问题是 1) 它们没有被导出,并且 2) 它们没有在 header 中声明,所以其他东西可以访问它们。所以我向它们添加了一个 __declspec(dllexport) (通过 RLOG_DECL 宏),并在标题中放置:

namespace rlog {
...
RLOG_DECL extern RLogChannel *_RLDebugChannel;
RLOG_DECL extern RLogChannel *_RLInfoChannel;
RLOG_DECL extern RLogChannel *_RLWarningChannel;
RLOG_DECL extern RLogChannel *_RLErrorChannel;
...
};

但无论我如何在 RLogChannel.cpp 中声明变量,我都会收到重新定义错误,尽管我在 header 中将它们外部化了......正确的方法是什么?看起来应该很简单,但我不能完全理解它。

编辑:错误信息

  Error 12  error C2086: 'rlog::RLogChannel *rlog::_RLDebugChannel' : redefinition  rlog-1.4\rlog\RLogChannel.cpp   45  rlog

(所有 4 个符号都相同)

编辑:我不知道发生了什么,代码和以前完全一样,但现在可以编译了(感觉像 MSVC 怪异......),不幸的是,当链接到我的库时,符号仍然显示为未解析

最佳答案

解决这个问题的一种方法是在一个地方和标题中定义它们一次。但是,如果您只是将所有定义转移到标题中,您最终会遇到多重定义问题。

解决方案是这样的。假设文件名为 rlog.c & rlog.h

--- (rlog.h) ---
#ifdef RLOG_DEFINES
#define EXTERN
#else
#define EXTERN extern
#endif


namespace rlog {
...
RLOG_DECL EXTERN RLogChannel *_RLDebugChannel;
RLOG_DECL EXTERN RLogChannel *_RLInfoChannel;
RLOG_DECL EXTERN RLogChannel *_RLWarningChannel;
RLOG_DECL EXTERN RLogChannel *_RLErrorChannel;
...
};


--- (rlog.c) ---
#define RLOG_DEFINES
#include "rlog.h"

...

--- (other .c files) ---
#include "rlog.h"

这个解决方案的美妙之处在于,因为定义只在项目中定义一次,所以您永远不会让它们彼此不同步,您只需要在一个地方更改它们。想象一下,如果您将一个变量定义为 long,但在 extern 定义中它被声明为 short?您最终可能会产生意想不到的副作用。所以这样做有助于防止这些类型的问题。

希望对您有所帮助。

关于c++ - 如何在命名空间中正确使用 extern?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2247681/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com