使用参数静态创建的全局类实例

时间:2013-04-26 10:50:58

标签: c++

是否可以使用静态创建的类实例,但是有参数?这就是我的想法:

/* main.cpp */
  int main(int argc, char ** argv){
    /* obtain parameters from command line and pass one of them to CLog*/
  }

/* CLog.h */
  class CLog{
    operator <<();
    /* some other stuff */
  };

  extern CLog log;

简而言之,我希望我的项目中的所有类都可以访问这个类,因此extern,我希望它被创建为非指针(以使用log<<"something"启用输出),但我想在创建它之前传递一个参数。那可能吗?或者是否有解决方法,以便我不必将其称为(*log)<<"something"

3 个答案:

答案 0 :(得分:2)

log的创建在调用main之前,因此您无法传递需要在main之后准备的参数。您可以通过以下方式传递参数:

class CLog{
    void setParameters(...);
     ...
    /* some other stuff */
};

extern CLog log;

...

int main(int argc, char ** argv){
    log.setParameters(...);
}

答案 1 :(得分:2)

您不能直接执行此操作,因为在main开始运行之前初始化全局变量。但是,您可以使用placement new

创建变通方法
#include <new>

char  CLogBuf[sizeof(CLog)];
CLog* pLog = nullptr;

int main(int argc, char** argv)
{
    pLog = new (CLogBuf) CLog(params);
    return 0;
}

是否值得,是你的决定。更直接的解决方案是@ M.M建议的解决方案。

在评论中讨论之后,这里是一个带引用而不是指针的版本,允许保留原始界面:

#include <new>

char  CLogBuf[sizeof(CLog)];
const CLog& log = *((CLog*)CLogBuf);

int main(int argc, char** argv)
{
    (void) (new (CLogBuf) CLog(params));
    return 0;
}

这种方法的主要优点是将接口减少到所需的最小值:没有什么能阻止不同方多次调用初始化方法,最有可能破坏程序语义。这种方法完全消除了init方法,从而消除了这个问题。

答案 2 :(得分:0)

我在这种情况下的偏好是在整个代码中使用一个访问器,它通过引用返回单例,以方便调用。访问器的实现可以简单地取消引用现有的全局,或者可以使用给定的参数懒得创建它,如下所示:

// In public header:
extern CLog & Log();

// In private cpp:
extern CLog & Log();
{
  static CLog * pLog = nullptr;
  if( !pLog )
    pLog = new pLog(/* params, which could be fetched from command line outside of main */);
 return *pLog;
}

// In client code:
Log().DoSomething();

如果您不喜欢parens,并且真的想要对象引用的外观和感觉,您可以创建一个包装器对象并通过operator-&gt;访问延迟创建的CLog,就像智能​​指针一样。< / p>