2016-09-15 7 views
0

Я читаю кучу «настроек» для приложения из XML-файла, и я хочу, чтобы эти параметры находились в пространстве имен, чтобы все мои функции могли иметь доступ. Я успешно выполнил эту работу, объявив переменные пространства имен в заголовке как 'extern int test;' а затем инициализировать их в исходном файле 'int test {0};'. Затем в исходном файле есть функция, которая читает XML и присваивает значение переменной пространства имен, и все это hunky dory.Как инициализировать глобальные константные переменные в пространстве имен со значениями из функции?

Проблема в том, что я понимаю, что я создаю ~ 100 переменных для чтения/записи, когда они должны быть постоянными. Поэтому я пытаюсь изменить свой код сейчас, когда они постоянны, и я не понимаю, как это возможно. Вот что я пробовал:

//settings.hpp 
#pragma once 
//header guard 

namespace settings { 
    extern const int ktest; 
} 

//settings.cpp 
void ReadXML() { 
    int testvalue{1}; //1 is default values 

    //here would be some code that gets value form XML and assigns it to testvalue 

    namespace settings { 
     const int ktest{testvalue}; 
    } 
} 

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

ответ

0

ОК, я не уверен, что если бы это было то, что дождевая клонит, но он вдохновил меня, чтобы найти это решение. Вот моя структура:

//xmlreader.hpp 
#pragma once 
//header guard 

int ReadXML(); 

namespace settings { 
    extern const int kreadsucces; //Has to be first, is result of read function 
    extern const int ktest; 
} 

//xmlreader.cpp 
#include "xmlreader.hpp" 
static int test {0};   //Default in case of exception in read function 

int ReadXML() { 
    //xml read code here, assign new 'test' value if successful 
    test = 2; 
    return 1; 
} 

namespace settings { 
    const int kreadsucces{ReadXML()}; //ReadXML is executed before main now! 
    const int ktest{test}; 
} 

//main.cpp 
#include "xmlreader.hpp" 
// if (ReadXML() > 0) {}    //Was old code, now called at initialization 
if (settings::kreadsuccess > 0) { 
    std::cout << "XML read succesful" << std::endl; 
} else { 
    std::cout << "XML read failed, using defaults" << std::endl; 
} 
std::cout << settings::ktest << std::endl; //Prints 2 

Что я сделал добавить «Настройки :: readsuccess» переменной и инициализировать его с моей функции вместо того, чтобы называть его в начале моей основной. Теперь эта функция фактически запускается сразу при запуске программы до начала основного запуска и присваивает все эти переменные владельца места, поэтому, когда другие переменные инициализируются, функции уже запущены.

Теперь я признаю, что я сделал немного ярлыка, но он работает, и теперь у меня есть пространство имен, полное 100 глобальных переменных const, инициализированных во время выполнения, которые доступны везде в моей программе, включая заголовок файл. Является ли это законным или лучше поставленным, это лучшая практика, чем просто наличие 100 изменчивых глобальных переменных?

+0

Я бы сказал, что проблема заключается не в том, есть ли у вас переменные или константные глобальные переменные. Я бы сказал, что проблема связана с глобальными переменными. И 100 из них. Это не хорошая практика программирования. –

+0

Я не утверждаю, что, но если бы у вас было 100 глобальных переменных, было бы лучше, если бы они были постоянными? Это изменение не требовало от меня перехода и изменения каждого исходного файла, но, по крайней мере, сделало его постоянным, я подумал, что это будет улучшение. – DrTarr

-1

Чтобы установить постоянную глобальную переменную, вам необходимо установить ее, когда она определена. Так делают это:

const int ktest = getValueofKtest(); 

Кроме того, установление сто переменных является кошмаром для обслуживания. Используйте класс настроек.

+0

Да, я просто прочитал [это] (http://stackoverflow.com/questions/26072216/c-global-extern-constant-defined-at-runtime-available-across-multiple-source-f) сообщение и там также была предложена функция возврата. Проблема, как вы сказали с функцией возврата, тогда мне придется написать функцию для каждой переменной, что означало бы, что мне придется открывать, читать и закрывать xml 100 раз. Не очень эффективно. Возможно, я создам одноэлементный класс и передам его по ссылке на все мои потоки. Все еще немного громоздко, чем использование пространств имен, но тогда я бы избежал изменчивых глобальных переменных? – DrTarr

+0

Функция для каждой переменной не означает, что вы должны прочитать xml для каждой переменной. –

0

объявить прототип функции в файле заголовка, тогда ваше пространство имен и инициализировать константу extern в зависимости от его возврата. затем определить свою функцию в основной:

//header.hpp 
#pragma once 

int RetValue(); // prototype 

namespace A{ 
    extern const int value(RetValue()); 
} 


//source.cpp 

int RetValue(){return 7;} // defining retValue 

int main() 
{ 
    cout << A::value << endl; // output: 7 
} 
+0

Я не вижу, как на практике это отличается от предложения Анона. Мне все равно придется создавать RetValue для каждой отдельной переменной, за исключением того, что я бы поставил инициализацию в файл заголовка вместо исходного файла. Есть ли польза там кроме очистителя (спорного) кода, потому что не нужно инициализировать переменные пространства имен в исходном файле? (Вместо этого мне пришлось бы поставить прототипы функций в файл заголовка). – DrTarr