外部声明的全局对象的 C++ 链接器错误

C++ linker error for extern-declared global object

我在使用 extern 声明的全局对象时遇到问题。据我了解,我应该能够在头文件中将对象声明为 extern,在源文件中定义它,然后在包含头文件的任何其他源文件中使用该对象。但是,对于以下结构,我收到一个链接器错误,指出 logger 符号未定义。

logger.hpp:

#ifndef MY_LOGGER_H
#define MY_LOGGER_H

namespace foo {
class Logger {
public:
    void log(int num);
};

extern Logger logger;
} // foo

#endif

logger.cpp:

#include "logger.hpp"
using namespace foo;

void Logger::log(int num) { /* Do stuff */ }

Logger logger;

main.cpp:

#include "logger.hpp"
using namespace foo;

int main() {
    logger.log(3); // arbitrary number
}

如果我在 main() 中声明 Logger,一切正常,因此头文件和源文件被正确包含和链接。 我在使用内置类型(例如 int)时遇到了同样的错误,所以我认为这也不是 Logger class 本身的问题。

抱歉,如果这是一个愚蠢的问题,我有几年的 C++ 经验,但直到现在我都避免像瘟疫这样的全局变量。

您需要将 logger.cpp 中的定义放在 foo 命名空间中:

#include "logger.hpp"

namespace foo { // not "using namespace foo"

void Logger::log(int num) { /* Do stuff */ }

Logger logger;  // this is now the "foo::Logger" you declared in logger.hpp
} // namespace foo

这个声明

Logger logger;

在全局命名空间中定义一个变量。

您需要使用限定名称来编写

#include "logger.hpp"

using namespace foo;

void Logger::log(int num) { /* Do stuff */ }

Logger foo::logger;

来自 C++ 20 标准(9.8.1.2 命名空间成员定义)

2 Members of a named namespace can also be defined outside that namespace by explicit qualification (6.5.3.2) of the name being defined, provided that the entity being defined was already declared in the namespace and the definition appears after the point of declaration in a namespace that encloses the declaration’s namespace

这是一个演示程序。

#include <iostream>

namespace foo {
    class Logger {
    public:
        void log(int num);
    };

    extern Logger logger;
} // foo

using namespace foo;

void Logger::log(int num) { /* Do stuff */ }

Logger foo::logger;

int main() 
{
    logger.log(3);
    
    return 0;
}