全局变量(再次) [英] Global variables (again)

查看:143
本文介绍了全局变量(再次)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不断听到全局变量应该从不 被使用,但我倾向于拒绝 从不 规则为热门。是否真的没有异常?

例如,我目前正在使用SDL在c ++中编写一个小游戏。在我看来,让一个全局变量有一个指向屏幕缓冲区的指针很有意义,因为所有代表不同类型的东西在游戏中的不同类将需要blit到它,并且只有一个屏幕缓冲。



请告诉我是否存在例外情况,如果不是的话:




  • 为什么不,或对他们有什么不好,他们应该不惜一切代价避免 (请解释一下)

  • 如何实现,最好不必将其传递给每个构造函数,以便在需要之前或每次调用paint()请求时存储在内部。



(我假设这个问题已经在SO之前被问过了,但是在搜索时找不到我需要的东西(解释和解决方法)

解决方案

当然也有例外。我个人不能想到一个单一的情况,goto是正确的解决方案(或单例是正确的解决方案),但全局变量偶尔有他们的用途。但是...你没有找到有效的借口。



游戏中的大多数对象都不会重复,不需要访问屏幕缓冲区。这是渲染器和没有人的责任。你不希望你的记录器,输入管理器,AI或任何人随机垃圾放在屏幕上。



这就是为什么人们说不使用全局 。这不是因为全局是一种最终的邪恶,而是因为如果我们不这么说,人们陷入了你陷入陷阱,是的,但这条规则不适用于 me ,对吗?我需要一切都可以访问X。不,你需要学会构建你的程序。



更常见的异常是无状态或静态对象,如记录器,或者你的应用程序的配置:都是只读或只写的,并且真正需要从随处访问。每行代码可能需要写一条日志消息。因此,记录器是做全球性的公平候选者。但是99%的代码甚至不需要知道屏幕缓冲区存在。



全局的问题是,它们违反了封装:
取决于全局的代码不太可重用。我可以采取与你使用的完全相同的类,把它放在我的应用程序,它会破裂。因为我没有它依赖的全局对象的相同网络。



这也使得代码更难理性。函数 f(x)返回什么值?
显然取决于 x 是什么。但如果我通过相同的 x 两次,我会得到相同的结果?如果它使用很多全局变量,那么可能不是。然后,它变得非常困难,只是弄清楚它会返回什么,以及什么它会做。是否会设置一些会影响其他看似无关的函数的全局变量?


如何实现这一点,将它传递给每个构造函数以在内部存储直到需要


你让它听起来像是一个坏事。如果对象需要知道屏幕缓冲区,那么您应该给它屏幕缓冲区。无论是在构造函数中,还是在稍后的调用中。 (它有一个很好的奖励:它提醒你如果你的设计是马虎的。如果你有500类需要使用屏幕缓冲区,那么你必须传递给500构造函数,这是痛苦的,所以它是一个唤醒调用:我做错了,很多对象不应该需要知道屏幕缓冲区,我该如何解决这个问题?



作为一个更明显的例子,假设我想计算1.42的余弦,所以我通过1.42到函数: cos(1.42)



这是我们通常的做法,没有全局变量。当然,我们可以改为说是的,但每个人都需要能够将参数设置为 cos ,我最好让它全局。然后它看起来像这样:

  gVal = 1.42; 
cos();

我不知道你,但我认为第一个版本更容易阅读。 >

I keep hearing that global variables should never be used, but I have a tendency to dismiss "never" rules as hot-headed. Are there really no exceptions?
For instance, I am currently writing a small game in c++ with SDL. It seems to me to make a lot of sense to have a global variable with a pointer to the screen buffer, because all the different class that represent the different type of things in the game will need to blit to it, and there is only one screen buffer.

Please tell me if I am right that there are exceptions, or if not then:

  • Why not, or what is so bad about them that they should be avoided at all costs (please explain a little bit)
  • How can this be achieved, preferably without having to pass it to every constructer to be stored internally until needed, or to every call to a paint() request.

(I would assume that this question had been asked on SO before, however couldn't find what I need (an explanation and workaround) when searching. If someone could just post a link to a previous question, that could be great)

解决方案

Of course there are exceptions. I personally can't think of a single situation where a goto is the right solution (or where a singleton is the right solution), but global variables occasionally have their uses. But... you haven't found a valid excuse.

Most objects in your game do not, repeat, not need to access the screen buffer. That is the responsibility of the renderer and no one else. You don't want your logger, input manager, AI or anyone else putting random garbage on the screen.

And that is why people say "don't use globals". It's not because globals are some kind of ultimate evil, but because if we don't say this, people fall into the trap you're in, of "yeah but that rule doesn't apply to me, right? I need everything to have access to X". No, you need to learn to structure your program.

More common exceptions are for state-less or static objects, like a logger, or perhaps your app's configuration: things that are either read-only or write-only, and which truly needs to be accessible from everywhere. Every line of code may potentially need to write a log message. So a logger is a fair candidate for making global. But 99% of your code should not even need to know that a screen buffer exists.

The problem with globals is, in a nutshell, that they violate encapsulation: Code that depends on a global is less reusable. I can take the exact same class you're using, put it in my app, and it'll break. Because I don't have the same network of global objects that it depends on.

It also makes the code harder to reason about. What value will a function f(x) return? It obviously depends on what x is. But if I pass the same x twice, will I get the same result? If it uses a lot of globals, then probably not. Then it becomes really difficult to just figure out what it's going to return, and also what else it is going to do. Is it going to set some global variable that's going to affect other, seemingly unrelated, functions?

How can this be achieved, preferably without having to pass it to every constructor to be stored internally until needed

You make it sound like that's a bad thing. If an object needs to know about the screen buffer, then you should give it the screen buffer. Either in the constructor, or in a later call. (And it has a nice bonus: it alerts you if your design is sloppy. If you have 500 classes that need to use the screen buffer, then you have to pass it to 500 constructors. That's painful, and so it's a wake-up call: I am doing something wrong. That many object shouldn't need to know about the screen buffer. How can I fix this?`)

As a more obvious example, say I want to calculate the cosine of 1.42, so I pass 1.42 to the function: cos(1.42)

That's how we usually do it, with no globals. Of course, we could instead say "yeah but everyone needs to be able to set the argument to cos, I'd better make it global". Then it'd look like this:

gVal = 1.42;
cos();

I don't know about you, but I think the first version was more readable.

这篇关于全局变量(再次)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆