I have trouble using an extern
-declared global object. As I understand it I should be able to declare an object as extern
in a header file, define it in a source file, then use the object in any other source file where the header is included. However, with the following structure, I get a linker error saying that the logger
symbol is undefined.
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
}
If I declare a Logger
in main()
, everything works fine, so the header and source files are being included and linked correctly.
I get the same error using built-in types (e.g. int
), so I don't think it's an issue with the Logger
class itself either.
Appologies if this is a dumb question, I have a few years' experience in C++ but I've avoided global variables like the plague until now.
This declaration
Logger logger;
defines a variable in the global namespace.
You need to write using qualified name
#include "logger.hpp"
using namespace foo;
void Logger::log(int num) { /* Do stuff */ }
Logger foo::logger;
From the C++ 20 Standard (9.8.1.2 Namespace member definitions)
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
Here is a demonstrative program.
#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;
}