摆脱库中的全局变量
Posted
技术标签:
【中文标题】摆脱库中的全局变量【英文标题】:Get rid of global variables in library 【发布时间】:2017-02-03 12:20:02 【问题描述】:我正在开发一个 MIDI 控制器库,它有几个类(例如,一类用于按钮,一类用于电位计,一类用于旋转编码器等)。所有这些类都有使用 sendMIDI 函数的方法。还有一个 setupMIDI 函数,在程序开始时调用一次。 setupMIDI 接受三个参数,需要通过 sendMIDI 函数访问。
类的定义
class Analog
public:
Analog (...) ...
void refresh ()
...
sendMIDI(x, y, z, ...);
...
class Digital ... (also uses sendMIDI) ...
etc.
setupMIDI 和 sendMIDI 函数
byte pin;
int delayTime;
bool debug;
void setupMIDI (byte p, int d, bool db = false)
...
pin = p; delayTime = d; debug = db;
...
void sendMIDI ( ... )
...
if(debug) ...
digitalWrite(pin, 1);
delay(delayTime);
...
实际程序:
Analog a1( ... );
Analog a2( ... );
Digital d1( ... );
setupMIDI(13, 10, true);
while(true)
a1.refresh(); // calls sendMIDI
a2.refresh();
d1.refresh();
如您所见,Analog 和 Digital 类的所有实例都使用相同的 sendMIDI 函数,这取决于在 setupMIDI 函数中输入的值。问题是这些值存储在全局变量中,并不理想。
我曾考虑过使用 MidiSender 类,但这需要将它的一个实例传递给每个 Analog 或 Digital 构造函数。
有没有更好的方法来解决这个问题?
非常感谢! 彼得
【问题讨论】:
您能否澄清一下这种说法:“[...] in global variables, which is not Ideal”?我同意下面的答案,将所有变量包装在一起的 context 肯定更好,但我不明白为什么全局声明它并通过引用传递它比简单地将它作为全局可访问更好静态资源,至少在它应该是一个单例的情况下。例如,同样的解决方案适用于Serial.begin(...)
。
问题是如果用户尝试创建一个pin
变量,库将无法工作。你能指出一个关于如何实现像串行这样的东西的链接吗?或者也许是一些搜索词?谢谢!
好吧,您可以使用 namespaces 来解决名称冲突,imho 这更多的是 good design 实践在同一 context 或 instance 中正确封装相关变量。但是,如果你的 midi 是一个 singleton,那么我看不出它是一个 global 和 有什么不好唯一的 实例。 Serial 的示例很容易理解,请查看“HardwareSerial0.cpp”中的声明(第 67-71 行)和“HardwareSerial.h/.cpp”中的类实现。 github上提供源代码:github.com/arduino/Arduino
【参考方案1】:
不要使用设置一些全局变量的setupMIDI
函数,而是使用MIDIContext
类来存储这些值并通过其构造函数对其进行初始化。
pin
、delayTime
和 debug
的用户要么是MIDIContext
的方法,要么采用MIDIContext&
(在适当的情况下使用const&
) em> 访问值。
例子:
class MIDIContext
private:
byte pin;
int delayTime;
bool debug;
public:
MIDIContext(byte x_pin, int x_delayTime, bool x_debug)
: pinx_pin, delayTimex_delayTime, debugx_debug
void sendMIDI();
;
class Analog
void refresh (MIDIContext& ctx);
;
可能的用法:
Analog a1( ... );
Analog a2( ... );
Digital d1( ... );
MIDIContext context(13, 10, true);
while(true)
a1.refresh(context);
a2.refresh(context);
d1.refresh(context);
【讨论】:
谢谢!我只是想知道是否有更简单的方法,而不必将上下文作为参数传递,但这似乎确实是最直接的方法。 这项技术对确保代码线程安全大有帮助。以上是关于摆脱库中的全局变量的主要内容,如果未能解决你的问题,请参考以下文章