2015-05-05 4 views
3

Я нашел фрагмент кода следующим образом.Когда использовать директивы препроцессора для определения функций в C++?

#define READWRITE READWIRTE 
#define READWIRTE(varType, varName, funName)    \ 
private: varType varName;         \ 
public: varType get##funName(void) const { return varName; }\ 
public: void set##funName(varType var){ varName = var; } 

READWIRTE(int, mSessionId, SessionId) 

Я хочу знать, почему бы не определить функцию в нормальной форме. Я имею в виду:

private: 
    int mSessionId; 
public: 
    public int getSessionId() const; 
    public void setSessionId(int sessionId); 

затем определить эти две функции.

Когда следует использовать директивы препроцессора?

+3

Это не определяет функцию. – juanchopanza

+1

Когда вы ленитесь! # ¤% & кто не заботится о читаемости. Также: '' (void) '' – Biffen

+1

Какой ответ вы ожидаете? Делай как хочешь. – Matt

ответ

2

Как сказано в [user258367], этот макрос помогает вам объявлять частные поля с открытым геттером и сеттер.

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

READWIRTE(int, mSessionId, SessionId) 

более кратким, чем полный код.

Но если это не обычное использование в корпоративной среде и включены в .h общей среди многих проектов, я бы не использовать его:

  • написание первого поля, а затем методы получения и установки кажется более общеупотребительный
  • он призывает всегда иметь геттер и сеттер даже один был useles (но, возможно, есть и другие макросы для ReadOnly и WriteOnly)
  • он оставляет вас неявным в public: видимости, которая может привести к путанице

    private: 
        int foo; // private, no need for getter or setter 
        READWIRTE(int, mSessionId, SessionId); 
        double bar; // is public ! 
    
    public: 
        void othermethod(); 
        ... 
    
1

Кажется, что это макрос для генерации «свойств» для классов. Автор, скорее всего, использует его как ярлык вместо того, чтобы вручную вводить частный член/accessor/mutator.

2

Этот макрос гарантирует, что с каждой переменной вы правильно определили свой сеттер и геттер.

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

1

Я вижу две веские причины, чтобы использовать макросы:

  • как здесь, как сокращение, чтобы избежать утомительной печатать;

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

1

Пожалуйста, не делайте этого.

Причина, по которой это делается, заключается в том, что она немного сбивает вас с клавиатуры. ОГРОМНЫЙ недостаток заключается в том, что он плохо мешает отладке.Предположим, что вы видите вызов setSessionId в области вашего кода, который может содержать ошибку. Вы ищете определение setSessionId. И вы не можете найти его. Не существует определения этого метода в любом месте исходного кода. Инструменты могут быть недостаточно умны, чтобы указать на макрос READ_WIRTE. Поэтому в этот момент вы полностью застряли. Вместо того, чтобы тратить пять секунд на поиск определения метода и видя, что он просто устанавливает переменную-член и, вероятно, безвреден, вы тратите возрасты на поиск определения функции.

(Некоторые люди могли бы утверждать, что вы должны ожидать setSessionId просто установить переменную-член. Не верно, когда у вас есть ошибка в вашем коде. Вы знаете, что-то не делать то, что вы ожидаете, что делать).

1

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

  1. В этом случае вряд ли добавляется какая-либо ценность при простом добавлении публичной переменной-члена, поскольку функции просто устанавливают или возвращают значение.
  2. Вполне возможно, что одна из двух функций может не понадобиться. Например, если вы используете RAII, значение устанавливается при построении объекта, добавление сеттера может не потребоваться или фактически быть нежелательным.
  3. Это может не поддерживать большие объекты вообще или эффективно.
  4. Он не будет (в текущей форме) быть потокобезопасным.
  5. Если код, который использует это, также сгенерирован или использует аналогичные макросы, в какой-то момент эти вызовы функций будут вызываться по клиентскому коду, чтобы геттеры и сеттеры должны были быть закодированы вручную (хотя они не 't строго появляться в заголовках) и ...
  6. ... отладка будет сложнее при просмотре исходного кода для определения, например, setSessionId() его нигде не будет найдено.

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

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

  • Нет связанных вопросов^_^