多线程设计,用C ++保护全局成员

时间:2012-10-30 16:18:03

标签: c++ multithreading global member

我正在用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
}

如果您对我有一些设计理念,我会很高兴,非常感谢!

3 个答案:

答案 0 :(得分:0)

class MyPrivateObjectClass : private MyObjectClass
{
public:
   friend void main();
};

extern MyPrivateObjectClass g_InitializedInMain;

答案 1 :(得分:0)

创建全局变量static,这意味着只有一个源文件可以访问它。然后,您可以提供可以从其他线程读取数据的访问器函数。

答案 2 :(得分:0)

对于初学者,我会不惜一切代价避免全局变量。

你可以做的而不是全局变量是在main中实例化一个变量(或者 动态地,或在堆栈上本地,取决于您的偏好) 并将其设置在线程对象中(这称为dependency injection

要仅从main控制MyObjectClass上的设置属性,我可以考虑2个选项:

  1. 通过main中的构造函数设置所有MyObjectClass属性,从而允许您删除setter,但保留getter。 MyObjectClass是不可变的。

  2. 创建一个上下文对象,其中包含MyObjectClass的所有可设置属性。此上下文对象只能传递给MyObjectClass构造函数。应该在main中创建上下文对象,调用适当的setter,然后在从main实例化时传递给MyObjectClass。 MyObjectClass类在内部使用来自上下文对象的这些属性,但没有为它们设置setter。当然,MyObjectClass上可以使用getter来获取内部上下文对象的值。 MyObjectClass是不可变的,但这种方式更灵活。

  3. 我更喜欢第二种选择。这是一个代码示例:

    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
    }