2012-01-16 2 views
1

я быть_наст ситуации, в C++, где мне нужно:по умолчанию/пользовательские значения для переменных в пространстве имен

1) определяет значение «по умолчанию» для статических переменных константных в пространстве имен объявленного /, определенных в модуле

объекта

2) позволяют несколько «основной» программы «перезаписать» эти значения, используя «обычай» значение

каждую «основная» программа имеет свою собственную папку сборки и свою собственную копию объект модуля, так что «основные» программа полностью независимы друг от друга:

например

/mainProgramA/build/mainProgramA.o 
/mainProgramA/build/Module.o 
/mainProgramB/build/mainProgramB.o 
/mainProgramB/build/Module.o 

также в любое время будут определены/объявлены значения по умолчанию или пользовательские значения, но не оба. если компилятор «находит» пользовательские значения, они будут использоваться, если нет, будут использоваться значения по умолчанию.

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

уточнить, я пытаюсь сделать что-то вроде этого:

DefaultValues.h:

namespace ConfigParams { 
    static const int param1 = 1; 
    static const int param2 = 2; 
} 

CustomValues.h:

namespace ConfigParams { 
    static const int param1 = 100; 
    static const int param2 = 200; 
} 

module.h:

#include "DefaultValues.h" 
class Module { 
public: 
    static void printParam1(); 
} 

Module.cpp:

#include "Module.h" 

void Module::printParam1() 
{ 
    printf("%d\n", param1); 
} 

mainUsingDefaultValues.cpp (который соединит в копию module.o где param1 == 1):

#include "Module.h" 

... 
Module::printParam1(); // Should print "1" 

mainUsingCustomValues.cpp (который соединит в копии module.o где param1 == 100):

#include "CustomValues.h" 
#include "Module.h" 

... 
Module::printParam1(); // Should print "100" 
+0

Включить или 'DefaultValues.h' или' CustomValues.h', но не оба. Вы можете сделать это по-другому, но я бы сказал, что используйте '# define' в' CustomValues.h', а затем проверьте, определено ли это в 'Module.h' и включает в себя' DefaultValues.h' на основе этого. – lapk

+0

@AzzA Я думаю, это не способ сделать это. Константы должны быть скомпилированы и связаны с абсолютным адресом для этого, когда вы определяете класс два раза с разными константами, он должен привести к одному в реальном приложении. – Vyktor

+0

@Vyktor Я думаю, что вопрос заключается в том, как исключить значения по умолчанию, когда заданы специальные значения. Вы можете сделать это с препроцессором ... Или, может быть, я неправильно понял. Я понимаю это, поскольку вы либо выбираете тот или иной, и автору OP нужен способ его выбора. Вы не можете использовать оба, конечно, вы можете включить тот или иной. – lapk

ответ

2
// File: CustomValues.h 
#define MY_CUSTOM_VALUES 
namespace ConfigParams 
{ 
static const int param1 = 100; 
static const int param2 = 200; 
} 


// File: DefaultValues.h 
#ifndef MY_CUSTOM_VALUES 
namespace ConfigParams 
{ 
static const int param1 = 1; 
static const int param2 = 2; 
} 
#endif 

вы можете сделать его более гибким, если вам это нужно.

EDIT: На всякий случай я неправильно понял вопрос. Таким образом, пользователь вашей библиотеки по умолчанию будет равен DefaultValues.h, если только они не включают CustomValues.h до Module.h. Вы можете иметь тот или иной, но не тот, и другой.

#include "Module.h" 
#include "CustomValues.h" 

не будет компилироваться, поскольку вы будете переопределять свои константы.

И только для того, чтобы убедиться, что вы должны включить CustomValues.h в Module.cpp.Так, наверное, это лучше сделать #ifdef переключатель внутри Module.h и сделать пользователя #define MY_CUSTOM_VALUES где-то до того, как Module.h включает в себя:

// File: Module.h 
#include "My_Constants.h" // #define MY_CUSTOM_VALUES can go here 
#ifdef MY_CUSTOM_VALUES 
#include "CustomValues.h" 
#elif 
#include "DefaultValues.h" 
#endif 

class Module 
{ 
public: 
    static void printParam1(); 
} 
// End of Module.h 

// File: Module.cpp 
#include "Module.h" 

void Module::printParam1() 
{ 
printf("%d\n", ConfigParams::param1); 
} 
// End of Module.cpp 
+0

Я блуждаю ... Static сообщает компилятору и компоновщику, что эта переменная должна быть инициализирована в начале программы и должна быть там все время. Не так ли? И когда компоновщик видит две переменные с тем же именем, оба статические ... Разве он (не должен?) Использовать один и тот же «абсолютный адрес в памяти»? – Vyktor

+0

@Vyktor Еще раз, '# define' предназначен для препроцессора, чтобы обойти определение по умолчанию, если поставляется таможня. По умолчанию они будут удалены препроцессором и не будут компилироваться. – lapk

+0

Я понимаю это, но, хотя я 'static const' имеет глобальную область действия (после ссылки), и поэтому компоновщик пытается перевести все их в одно и то же« место памяти ». Или все они находятся в локальной области, если не используется «extern»? – Vyktor

Смежные вопросы