如何通过"extern"获取C++中的"global"类对象
How to obtain a "global" class object in C++ via `extern`
我在论坛上检查了几个关于这个主题的答案,但由于某种原因,我仍然无法思考这个问题并让我的作品运行。
我的目标是在所有翻译单元中提供类的一个对象。请注意,我不寻求在这里实现单例模式。该类可以有多个实例,但总会至少有一个实例,可以在包含"其标头"的位置看到这个实例。
假设这样的设计:
---logging.h---
class LogCenter {
...
}
class Logger {
private:
LogCenter& center;
public:
Logger(); //automatically assigns the ominous global LogCenter object (reference) to center.
Logger(LogCenter&); //however, any other LogCenter object would work equally fine.
}
原因何在?我希望所有Logger
都可以默认使用此全局LogCenter
,无论它们在哪里使用。但是现在我不确定如何提供这种全球LogCenter
.它具有默认构造函数。我是否只是在logging.h
文件中添加一行extern LogCenter globalCenter;
,在logging.cpp
文件中添加另一行LogCenter globalCenter;
行?或者只是LogCenter globalCenter;
logging.cpp
中并extern LogCenter globalCenter;
使用它的任何文件中?
真的很困惑,我尝试过的方法都没有奏效 - 但是,当我将构造函数重载与其自己的LogCenter
实例一起使用时,整体代码运行良好。
编辑:重要:extern
与声明一起使用(例如在头文件中(。然后在实现文件中使用单个定义。
检查所有答案!
这是它的工作原理:
---logging.h---
class Entry;
class LogCenter {
friend class Logger; //please don't bash my friend design right away... D:
private:
list<Entry> entries;
public:
void printLog(string file);
}
extern LogCenter SCenter;
class Logger {
private:
LogCenter& center;
public:
Logger(); //uses extern or "singleton" object.
Logger(LogCenter&);
void commitEntry(Entry); //adds the Entry object to the list in the center object.
}
-----------------
---logging.cpp---
#include "logging.h"
LogCenter SCenter;
void Logger::commitEntry(Entry e) {
entries.push_back(e); //Logger can access LogCenter fields!
}
void LogCenter::printLog(string file) {
//open file stream str
for(list<Entry>::iterator it = entries.begin();...)
str << it->getEntry() << endl;
//close file
}
--------------
---main.cpp---
#include "logging.h"
int main() {
Logger log;
Entry e("Some entry");
log.commitEntry(e);
SCenter.printLog("filename.log");
//or
LogCenter cent;
Logger log(cent);
Entry e("some entry");
log.commitEntry(e);
cent.printLog("filename.log");
return 0;
}
-------------
使用 extern
变量是一个选项。
另一种选择是有一个返回引用的函数。
logging.h:
LogCenter& getGlobalLogCenter();
日志记录.cpp:
LogCenter& getGlobalLogCenter()
{
static LogCenter lc;
return lc;
}
//logcenter.h
#ifndef LOGCENTER_H_
#define LOGCENTER_H_
class LogCenter {
private:
int dummy;
public:
int getVal(){ return dummy; };
LogCenter() : dummy(0){};
LogCenter(int val) : dummy(val) {};
};
#endif // LOGCENTER_H_
三十
// logcenter.cpp
#include "LogCenter.h"
LogCenter globalCenter;
三十
//logger.h
#ifndef LOGGER_H_
#define LOGGER_H_
#include <string>
#include "LogCenter.h"
class Logger {
private:
LogCenter& center;
public:
Logger(); //automatically assigns the ominous global LogCenter object (reference) to center.
Logger(LogCenter&); //however, any other LogCenter object would work equally fine.
std::string print() { return std::string("This class uses logger ") + std::to_string(center.getVal()); };
};
#endif // LOGCENTER_H
三十
// logger.cpp
#include "Logger.h"
extern LogCenter globalCenter;
Logger::Logger() : center(globalCenter) {};
Logger::Logger(LogCenter &logcenter) : center(logcenter) {};
三十
// main.cpp
#include "Logger.h"
int main(int argc, char* argv[])
{
LogCenter logcenter2(2), logcenter3(3);
Logger logger1, logger2(logcenter2), logger3(logcenter3);
std::cout << logger1.print() << std::endl;
std::cout << logger2.print() << std::endl;
std::cout << logger3.print() << std::endl;
return 0;
}
输出为:
This class uses logger 0
This class uses logger 2
This class uses logger 3
我建议您使用以下C++单例模式,该模式易于使用,在跨共享库使用时甚至是安全的:
// LogCenter.h
class /*API_MACRO_FOR_EXPORTING*/ LogCenter {
public:
static LogCenter* instance();
}
// For quick access you could define a macro
#define sLogCenter
LogCenter::instance()
// LogCenter.cpp
LogCenter* LogCenter::instance()
{
static LogCenter instance;
return &instance;
}
// LogCenter::instance()->DoSomething();
// sLogCenter->DoSomething();
要回答您关于外部的问题:
// LogCenter.h
// You can use multiple definitions with extern so the compiler
// knows the LogCenter is instantiated somewhere else.
extern LogCenter globalCenter;
// LogCenter.cpp
// Only 1 declaration of LogCenter
/*API_MACRO_FOR_EXPORTING*/ LogCenter globalCenter;
我会选择第二个选项,即"extern LogCenter globalCenter;",在使用它的文件中。
如果有人包含logging.h,原因可能是为了创建Logcenter类的新对象,但不打算使用globalCenter对象,那么为什么他需要globalCenter对象的extern声明。
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- .cpp和.h文件中的模板专用化声明
- 反向给定链表中的K节点
- 正在查找文档以获得PS4平台的C++中的设备信息
- enum是C++中的宏变量还是整数变量
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 将字符串存储在c++中的稳定内存中
- 文本文件中的单词链表
- 递归函数计算序列中的平方和(并输出过程)
- 如何从C++中的依赖类型中获得它所依赖的类型
- C++中的"inline"关键字
- 如何运行位于boost/libs/python/example/tutorial目录中的hello.cpp和Jamfil
- 如何使用 < 和 > 命令获取 c++ 中的输入和输出?
- 用C++中的一个变量定义一个常量
- vector.resize()中的分配错误
- 使用指针从C++中的数组中获取最大值
- arr[-1]在c++中的奇怪行为
- 在 .h 文件中的类中声明静态变量和在.cpp文件中声明"global"变量有什么区别
- 如何阅读C++中的NetCDF "global attribute"
- 如何通过"extern"获取C++中的"global"类对象