外部声明的全局对象的 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;
}
我在使用 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;
}