隐藏C ++命名空间中的变量

时间:2012-01-08 21:39:48

标签: c++ namespaces

我有一个旨在执行递归计算的函数。如果我的函数是递归编程的,那么计算时间太长。因此,我通过将中间结果存储在数组中来执行memoization。

在我的程序执行期间,我可能会使用参数(10,0)(5,5)(2,4)等来调用该函数。因此,我有一个setup(double x)函数可以填充整个具有正确值的数组。然后我可以访问任何数组值而无需进一步计算。我只等到x更改后再次致电setup()

我想知道如何在c ++中实现它。我使用类没有意义,因为我永远不需要创建关联的对象。我已经在命名空间中实现了很好的功能,但我仍然遇到了问题。即使我使用未命名的命名空间,我的函数使用的数组也是可见的,并且可以从函数的命名空间外部进行修改。如果我包含命名空间的头文件,那就是。

我的代码:

FunctionWrapper.h

namespace FunctionWrapper{
      namespace{
            double tempArray[10][10];
      }

      void setup(double x);
      void getValues(int n);
}

Main.cpp的

#include "FunctionWrapper.h"

int main(){
   FunctionWrapper::tempArray[0][0] = 5; //Works
}

4 个答案:

答案 0 :(得分:6)

如果您不希望tempArray在其他源文件中可以命名,请不要在头文件中声明它。而是在 FunctionWrapper.cpp 中的未命名命名空间中声明它。然后,它只能直接在该源文件中使用。

通常,头文件不应使用未命名的命名空间,因为它可能(并且经常会)导致违反一个定义规则。

请注意,更好的解决方案可能是创建一个提供此功能的类:

class ValueGetter
{
public:
    ValueGetter(double x);
    void GetValues(int n);

private:
    double cache[10][10];
};

这样,您可以创建此类型的实例,并且该实例拥有所有状态。避免全局状态有很多好处,包括提高可维护性和可测试性。

答案 1 :(得分:1)

这作为一个类有意义,而那些函数作为该类的成员。这些函数对这些数据起作用,你不希望任何其他人访问这些数据,这听起来像是一个完美的类。你为什么反对呢?

答案 2 :(得分:1)

继詹姆斯(通常,优秀)答案之后,我会构建类似这样的东西:

namespace {
class value_cache { 
     double temp_array[10][10];
     int x;
     void setup(double x);
     void internal_getValues(int); // same as your current GetValues
public:
     void getValues(int n) { 
         if (x != n) 
            setup(x=n);            
         internal_getValues(n);
     }
};
}

double function(int x, int y) {
     static value_cache c;

     c.getValues(x); 
     // probably more stuff here.
}

答案 3 :(得分:0)

我在这里看到三个选项:

  1. 将匿名命名空间放在实现memoized函数的.cpp文件中。然后它将无法从其他任何地方进行访问。
  2. 使包含memoized结果的数组在类中包含static变量。
  3. 创建一个实现operator ()的类,并使用它的实例作为“函数”。然后memoization数组可以是该类的私有成员变量。
  4. 选项1非常简单,它会起作用。当然,如果您的函数曾经在多线程环境中使用过,那么您将不得不考虑访问memoized value数据结构的线程间同步。

    选项2是选项1的变体。就个人而言,我认为这是你应该选择的那个。它有完全相同的缺点。

    选项3是,恕我直言,相当繁琐。为了拥有看起来像你的函数一样的东西,你必须声明一个类的全局变量。但这基本上是一个单身人士。虽然在这种情况下可能没问题,但最终可能会成为一个巨大的痛苦。

    还有另一种选择,但这是一项大量的工作。它基本上是一个记忆模板。它将像选项3一样运行,但您可以为任何参数满足作为hashmap键的标准的函数实例化它。