C ++ вложенные макросы? - PullRequest
       22

C ++ вложенные макросы?

2 голосов
/ 12 ноября 2009

Есть ли способ в C ++ определять вложенные макросы / константы внутри класса, аналогично вложенным определениям типов, или метод для достижения аналогичной функциональности? Мотив обычно используется макросами для шаблонов.

class SomeClass
{
public:
    #define SomeConstant 123
};

int x=SomeClass::SomeConstant;

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

Ответы [ 7 ]

8 голосов
/ 12 ноября 2009

Вы не можете делать то, что вы хотите с макросами. Макросы не имеют понятия области видимости.

Но для простых значений типа int вы можете делать то, что хотите, с помощью перечислений.

class SomeClass
{
public:
    enum {
        SomeConstant=123
        };
};

int x=SomeClass::SomeConstant;

Полное имя для значения, но для него не требуется места, даже в отладочных сборках - вы не можете получить его адрес, если хотите.

6 голосов
/ 12 ноября 2009

Константные значения, объявленные и определенные на месте, - это именно то, что вам нужно: компилятор может и будет оптимизировать их полностью, чтобы они в конечном итоге были такими же, как и использование #define, но с преимуществами строгое определение.

class SomeClass {
  public:
   static const int someValue = 10;
};

Это не занимает дополнительного места - память не выделяется для хранения "someValue". Вы можете доказать это: если вы попытаетесь использовать «someValue» в качестве реального объекта (т.е. вы попытаетесь получить его адрес), то компоновщик скажет вам, что он не определен.

2 голосов
/ 12 ноября 2009

Макросы полностью игнорируют область видимости - они раскрываются перед компиляцией C ++. Вы просто не можете этого сделать.

Использование статического const часто приводит к тому, что переменная не выделяется - компилятор рассматривает ее как константу.

1 голос
/ 12 ноября 2009

Вы можете сделать это с помощью шаблонов:

template < int someConstant = 123 > class SomeClass
{
public:
    void outputConstant() { cout << "We think the answer is:" << someConstant; }
}

Но это не совсем то, что вы хотите, потому что вы должны объявить экземпляр класса как:

int main(int argc, char *argv)
{
    SomeClass<123> myInstance;
}

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

Авторитетная книга на эту тему (программирование с помощью шаблонов на этапе компиляции): Современный дизайн на C ++: применение шаблонов общего программирования и проектирования, Андрей Александреску .

1 голос
/ 12 ноября 2009

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

Для того, что вы хотите, либо используйте статический констант, либо используйте полное имя (при условии, что препроцессор допускает двоеточия в именах макросов, не уверен на 100% в этом) - хотя это не позволит вам наследовать константу в производных классах :

#define SomeClass::SomeConstant 123
0 голосов
/ 12 ноября 2009

«Статические члены - это физические переменные».

Что против этого? Единственная причина возражать против этого - использование памяти. Но поскольку элемент является статическим, память будет занята только один раз предполагаемым содержимым.

Напротив, с макросом, аргумент будет присутствовать в каждом месте использования в двоичном файле.

EDIT: Если переменная имеет целочисленный тип, меньший, чем указатель, вероятно, лучше определить константу в объявлении класса. Оптимизирующие компиляторы могут затем встроить значение в вызывающий код, как для макроса.

0 голосов
/ 12 ноября 2009

Я не понимаю вашего возражения против использования статического констант. Это не повлияет на размер вашего класса, и компилятор оптимизирует для достижения того, что вы думаете, что вы получите от макроса.

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