Скрытие переменных в пространстве имен C ++ - PullRequest
3 голосов
/ 09 января 2012

У меня есть функция, которая предназначена для выполнения рекурсивных вычислений. Если моя функция запрограммирована рекурсивно, вычисление занимает слишком много времени. Поэтому я выполняю запоминание, сохраняя промежуточные результаты в массиве.

Во время выполнения моей программы я мог бы вызвать функцию с параметрами (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 ]

6 голосов
/ 09 января 2012

Если вы не хотите, чтобы tempArray был доступным для имени в других исходных файлах, не объявляйте его в заголовочном файле.Вместо этого объявите его в безымянном пространстве имен в FunctionWrapper.cpp .Тогда его можно использовать только непосредственно из этого исходного файла.

Как правило, заголовочный файл не должен использовать безымянное пространство имен, поскольку это может (и часто будет) приводить к нарушениям одного правила определения.

Обратите внимание, что лучшим решением вашей проблемы может быть на самом деле создание класса, обеспечивающего эту функциональность:

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

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

Таким образом, вы можете создать экземпляр этого типа и всегосударство принадлежит этому экземпляру.Избегание глобального состояния дает много преимуществ, в том числе повышается удобство обслуживания и тестируемость.

1 голос
/ 09 января 2012

В дополнение к ответу Джеймса (как обычно, отлично) я бы структурировал что-то вроде этого:

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.
}
1 голос
/ 09 января 2012

Это имеет смысл как класс, и эти функции как члены этого класса. Эти функции действуют на эти данные, и вы не хотите, чтобы кто-то еще имел доступ к этим данным, что звучит как идеальное использование для класса. Почему ты против этого?

0 голосов
/ 09 января 2012

Я вижу здесь три варианта:

  1. Поместить анонимное пространство имен в файл .cpp, в котором реализована ваша запомненная функция.Тогда он не сможет получить доступ из других источников.
  2. Сделать массив, содержащий запомненные результаты, переменной static внутри класса.
  3. Создать класс, реализующий operator (),и использовать его экземпляр как свою «функцию».Тогда массив памятки может быть закрытой переменной-членом этого класса.

Вариант 1 очень упрощенный, и он будет работать.Конечно, если ваша функция когда-либо используется в многопоточной среде, вам придется подумать о межпоточной синхронизации доступа к структуре данных запомненных значений.

Вариант 2 - это вариант опции1. Лично я думаю, что это тот, который вы должны пойти.У него точно такой же недостаток.

Вариант 3, ИМХО, довольно неудобный.Чтобы иметь что-то похожее на вашу функцию, вам нужно объявить глобальную переменную класса.Но это в основном синглтон.И хотя в этом случае все может быть в порядке, в будущем это может стать огромной болью.

Есть еще один вариант, но это огромный объем работы.Это в основном делает запоминающийся шаблон.Он будет работать как вариант 3, но вы можете создать его экземпляр для любой функции, аргументы которой удовлетворяют критериям для того, чтобы быть ключами хэш-карты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...