多线程设计,保护C++中的全局成员
Posted
技术标签:
【中文标题】多线程设计,保护C++中的全局成员【英文标题】:Multithreading Design, protect global member in C++ 【发布时间】:2012-10-20 01:09:36 【问题描述】:我正在使用 QT 编写一个 c++ 应用程序,重点是速度优化。 我想要一些对不同线程具有只读访问权限的全局对象。 在打开线程之前,我必须初始化全局对象并用数据填充它们。
如何保护我的全局对象的集合函数,但仍可以从主函数访问?
现在的示例代码:
myClass.h
class MyObjectClass
public:
void SetSome(const QList<QString> &value);
QList<QString> GetSome() const;
private:
QList<QString> m_myMember;
;
main.cpp
#include "global.h" // some like: extern MyObjectClass g_InihalizedInMain;
#include "anyThread.h"
int main()
g_InitializedInMain.SetSome() // This Shut work
MyThread thread;
thread.start();
//..
return 0;
anyThread.cpp:
#include "global.h"
void thread::run()
MyObjectClass newObject = g_InihalizedInMain; //This shut work
g_InitializedInMain.GetSome(); //This shut work
g_InitializedInMain.SetSome(); //This shut not work and give me an error during compile time
newObject.SetSome(); //This shut work
如果您有一些设计想法给我,我会很高兴,非常感谢!
【问题讨论】:
我会尝试使用friend
声明。
【参考方案1】:
class MyPrivateObjectClass : private MyObjectClass
public:
friend void main();
;
extern MyPrivateObjectClass g_InitializedInMain;
【讨论】:
【参考方案2】:创建你的全局变量static
,这意味着只有一个源文件可以访问它。然后,您可以提供可以从其他线程读取数据的访问器函数。
【讨论】:
【参考方案3】:对于初学者,我会不惜一切代价避免使用全局变量。
除了全局变量之外,您可以做的是在 main 中实例化一个变量(或者
动态地,或在堆栈上本地,取决于您的偏好)
并将其设置在线程对象中(这称为dependency injection
)
要仅从 main 控制 MyObjectClass 的设置属性,我可以想到 2 个选项:
通过 main 中的构造函数设置所有 MyObjectClass 属性,从而允许您删除 setter,但保留 getter。 MyObjectClass 将是不可变的。
创建一个包含 MyObjectClass 的所有可设置属性的上下文对象。此上下文对象只能传递给 MyObjectClass 构造函数。上下文对象应该在 main 中创建,调用适当的设置器,然后在从 main 实例化时传递到 MyObjectClass。 MyObjectClass 类在内部使用上下文对象的这些属性,但没有它们的设置器。 MyObjectClass 上当然会有可用的 getter,它会从内部上下文对象中获取值。 MyObjectClass 将是不可变的,但这种方式更灵活。
我更喜欢第二种选择。这是一个代码示例:
myClass.h
class MyObjectContext
public:
void SetSome(const QList<QString> &value);
QList<QString> GetSome() const;
private:
QList<QString> m_myMember;
;
class MyObjectClass
public:
MyObjectClass(MyObjectContext *context) : context_(context)
QList<QString> GetSome() const return context_->GetSome();
// Put the rest of the important stuff here
private:
MyObjectContext *context_;
MyObjectClass(); // explicitly stating that the default ctor cant be called
;
main.cpp
int main()
// creating these objects on the stack, you may need
// to create them dynamically, its up to you
MyObjectContext context;
context.SetSome() // This Should work
MyObjectClass moc(&context);
MyThread thread(&moc);
thread.start();
//..
return 0;
anyThread.h
class MyThread : public QThread // Assuming you're inheriting from QThread
public:
// instead of setting it via the ctor, you could consider adding a setter
MyThread(MyObjectClass *moc) : moc_(moc)
void run();
private:
MyThread(); // explicitly stating that the default ctor cant be called
MyObjecctClass *moc_
;
anyThread.cpp
void MyThread::run()
moc_->GetSome(); //This should work
// Dont have to worry about the setters, since there are none
// available for the MyObjectClass, which is now immutable
【讨论】:
以上是关于多线程设计,保护C++中的全局成员的主要内容,如果未能解决你的问题,请参考以下文章