重构大案例陈述,外部,静态本地

时间:2014-04-11 22:07:49

标签: c++ extern

我试图做一些重构,并希望找到最好的前进道路。

我有

  myonce{
    static int i //for operation 1
    switch(commandid) {
       case 1:  operation 1
                i = 1;
       ...

其中myonce是一个在循环中调用的函数。这不是我的代码,我试图让它变得更好。操作1(或每种情况)是一系列命令,我想将它们放在自己的翻译单元中(每个文件一个函数)。

由于myonce在循环中运行,原始作者有许多静态变量用于保持状态,其中一些状态集用于多个操作。请注意,这些不是静态文件范围,它们是静态块范围。

为了简单起见,作为概念证明,我想知道以下是否可行。 考虑使用1组静态变量进行1次操作。

的main.cpp

myonce {
   static int i //for op 1
   switch(commandid) {
       case 1:  operation1();

operation1.cpp

extern int i;
void operation1() {
   i = 1;
}

在使用相同状态集的多个操作的情况下,我会创建一个标题来将它们全部声明为extern。

目前这个文件的编译计算在几分钟内,我的第一个目标是将其分解为较小的编译单元,以便作者可以更自由地工作。这种重构需要很长时间,但我提到这是对我采用这种方法的动机的解释。

据我所知,其他翻译单元(其他文件中的extern)无法访问静态文件范围变量,因此我希望能够区分出我处理的情况并非如此。我现在不知道的是,我应该将operation1()声明为main,如果它是

static int i
extern void operation1();

那么int声明为函数可见吗?

我很感激这方面的任何指示。感谢。

3 个答案:

答案 0 :(得分:1)

不,你不能这样做。 static个对象在其他源文件中不可见。

你的switch有多大?修改它的原因是什么?

也许原始程序员有充分理由知道本地静态变量?你说它是在循环中调用的,并且一些静态变量用于将状态从一次迭代保持到下一次迭代,在交换机的分支之间共享。构建代码当然是一种奇怪的方式。我可以考虑做这样的事情来运行某种有限的自动机,但在这种情况下,我会将自动机编写为每个状态的一串代码片段,并通过直接goto在它们之间进行传输。我会将某些放在非常接近的地方,以更易读的形式描述自动机。

但我可能完全偏离基础。你能分享一下这个代码的作用吗?

答案 1 :(得分:1)

首先,通过使用其功能创建更好的数据结构(例如,具有虚拟成员函数command的类,其实现做正确的事情),通常可以避免切换。

在一个不那么雄心勃勃的层面上,你可以只将指针传递到该特定情况下需要的静态函数,以便它可以读取和修改这些变量的状态。

根据函数的作用,还可以将状态信息作为值参数(副本)传递,让函数根据该状态执行工作,接收结果,然后根据结果更改主开关中的全局状态。然后状态变化清晰可见(即功能中没有副作用),并且嘈杂的分散注意力的细节被禁止到另一个文件。

如果每个案例都倾向于使用许多静态变量,那么你可以将它们全部放在一个结构中;该更改应该可以使用文本编辑器(用mystruct.x替换变量名x等)。然后每个函数只获得一个指向该结构的指针。编辑:正如我在评论中所说:也许命令自然形成仅涉及状态部分的组(例如,只有读取的命令,其他只写数据等的命令)。然后,全局状态可以分成相应的数据组。每个函数只能查看与之相关的数据组,从而限制了潜在的副作用。

但一般来说,这个功能现在看起来很糟糕/随着时间的推移而增长;处理大量静态变量意味着在代码中都存在“副作用” - 不容易看出代码的任何给定部分的作用以及它与其他部分的交互方式。信息流不明确。分析属于一起的数据集群,在类中组织它们并在文件中将它们分开将是一项任务,即使没有任何虚拟成员函数也是如此。

关于你的上一个问题:你创建的“案例函数”(operation1();等)只需要在调用它们的文件中知道。如果它们位于一个或多个单独的文件中,您应该创建一个包含原型的标题。

答案 2 :(得分:1)

将状态变量放入结构中。将此结构传递给每个函数。

实施例

// foo.h
struct TheState
{
    int x;
    char *y;
    // ...
};

void func1(TheState &);
void func2(TheState &);

// main.cc
#include "foo.h"

void main_loop()
{
     TheState the_state;  // initialize this however you want

     for (;;)
     {
          if ( blah) func1(the_state);
          else func2(the_state);
     }
}

// func1.cc
#include "foo.h"

void func1(TheState &the_state)
{
     ++the_state.x;
}