做全局变量的正确“C ++方式”是什么?

时间:2009-04-21 13:58:20

标签: c++ design-patterns oop

我有一个主应用程序类,其中包含一个记录器,以及一些常规应用程序配置等。

现在我将显示许多GUI窗口等(将使用记录器和配置),我不想将记录器和配置传递给每个构造函数。

我已经看到了一些变体,比如在任何地方声明主类extern,但这并不是非常面向对象的。什么是使主类中的元素可供所有(或大多数)其他类访问的“标准”C ++方法?

11 个答案:

答案 0 :(得分:12)

使用singleton design pattern

基本上,您返回一个对象的静态实例,并将其用于您的所有工作。

请参阅此link about how to use a singleton以及此stackoverflow link about when you should not use it

警告:单身模式涉及促进全球状态。全球国家有很多原因 例如:单元测试。

答案 1 :(得分:7)

如果你的记录器和配置足够抽象,那么将记录器和配置传递给所有构造函数并不是一件坏事。

单身人士将来会成为一个问题。但它在项目开始时就像是一个正确的选择。你的选择。如果您的项目足够小 - 请使用单身人士。如果不是 - 依赖注入。

答案 2 :(得分:6)

为什么不使用已经存在的系统?也就是说,将std :: clog重定向到输出到文件并写入std :: clog。

std::fstream *f = new std::fstream("./my_logfile.log")

std::clog.rdbuf(f->rdbuf());

std::clog << "Line of log information" << std::endl;

答案 3 :(得分:3)

我同意某种单身方法。你绝对不想在整个地方传递记录器对象。这将很快变得非常无聊,恕我直言是一个更糟糕的设计,而不仅仅是一个普通的全球对象。

对是否有一个好的解决方案的一个很好的测试是在需要它的函数中使日志工作所需的步骤。

如果你必须做的不仅仅是

#include "Logger.h"
...
void SomeFunction()
{
    ...
    LOGERROR << "SomeFunction is broken";   
    ...
}
...

然后你在浪费精力。

答案 4 :(得分:2)

记录属于aspect orient programming

中“关注点分离”的范畴

通常,日志记录不是对象的功能或关注点(例如,它不会更改对象的状态;它只是一种用于观察/记录状态的机制,并且输出在大多数情况下基本上是一次性的) 它是一个短暂的,通常是可选的辅助功能,不会对课程的操作有所贡献。 对象的方法可以执行日志记录,但是可以在那里完成日志记录,因为它是一个方便的地方,或者代码执行流中的那个点是人们希望记录状态的地方。

因为C ++不提供定义方面的工具,所以我倾向于简单地保留外部短暂对象,如loggers global,并将它们包装在命名空间中以包含它们。命名空间不是用于包含,所以这有点难看,但是由于缺少任何其他东西,它很方便,并且比在正式参数中传递记录器或在要记录的所有对象中引用它们要简单得多。如果在某些时候我决定不再需要记录器(即,如果它仅用于调试),这也可以更容易地删除记录器。

答案 5 :(得分:0)

我猜Service Locator会这样做。您必须在构造函数中传递,或者在一些众所周知的位置具有全局可访问的静态成员函数。前一种选择更为可取。

答案 6 :(得分:0)

不知道这是否对您的情况有帮助,但在MFC中,有/是一个应用程序类。

我习惯把这样的东西扔进那个班。

我假设您没有使用MFC,但如果您有应用程序类或类似的东西,这可能会有所帮助。

答案 7 :(得分:0)

我会避免单身模式 在测试方面遇到太多问题(见What is so bad about singletons?

我个人会将记录器等传递给构造函数。或者,您可以使用工厂创建/传递对资源的引用。

答案 8 :(得分:0)

为什么不使用log4cxx? 这些问题很久以前就被解决了,并被许多人广泛使用。 除非你正在构建一些非常特殊的日志记录系统...在这种情况下,我会使用Factory模式,它会为任何感兴趣的人创建记录器(或者如果它是单例,则赠送现有的实例)。其他类将使用工厂来获取记录器。在构造函数参数中传递记录器是一个坏主意,因为它将您的类与记录器耦合。

答案 9 :(得分:0)

只需将您的主类传递给您想要访问“所有内容”的其他类的构造函数

然后,您可以通过会员属性提供对记录器等的访问。 (原谅我的C ++语法,这只是一种被称为“被VB混淆的C ++”的虚构语言)

e.g。

Class App {
     Private  m_logger;
     Private  m_config;

     Public logger() {
        return m_logger;
     }

     Public config() {
        return m_config
     }
}

Class Window1 {
     New( anApp ) {
     }
     ....
}

答案 10 :(得分:0)

为什么没有人想到遗产和多态?您也可以使用具有该单例的抽象工厂;)