@oblepyx

Правильно ли в C++ использовать директиву препроцессора define?

Я начал изучать С++ около полугода назад и до сих пор не понимаю как относиться к define директиве препроцессора. Кто-то говорит что это крутая штука, а кто-то терпеть не может : /

В связи с этим пишу этот вопрос, чтобы окончательно для себя решить. К примеру использование пространства имен std через using namespace std не очень приветствуется из-за загрязнения текущего пространства имен. Тогда почему бы просто не написать:

#include <iostream>

#define COUT std::cout

int main(){
    COUT << "something\n";

    return 0;
}


Можете смело писать что я тупой, но объясните, могу я так писать хотя бы в своих личных проектах? А если не могу - то почему и есть ли какие-то альтернативы define. Заранее спасибо.
  • Вопрос задан
  • 146 просмотров
Решения вопроса 1
@Acaunt
define полезная штука и её не обязательно использовать так как ты (лично я не вижу смысла использовать её для этого).

Например:
Если у тебя много файлов ссылаются друг на друга то можно конечно использовать #pragma once, но эта штука работает не во всех компиляторах. Поэтому предпочтительнее использовать:
#ifndef FILE_H
#define FILE_H
#include "file1.h"
#include <iostream> например этот  заголовочный файл объявлен и в file1.h
#endif // !FILE_H


Ещё в заголовочном файле math.h есть константы (число пи например), но они скрыты если не объявлен #define _USE_MATH_DEFINES

Подобную штуку я использовал в своем проекте вот пример:
#if TYPE_64
using type = uint64_t; 
#elseif defined(TYPE_32)
using type = uint32_t; 
#elseif defined(TYPE_16)
using type = uint16_t; 
#else
using type = uint8_t; 
#endif


Ещё можно подобные штуки расставить по всему коду для вывода информации о работе программы на проверку есть ли #define DEBUG, а когда программа готова то просто убрать этот define и программа будет чуть быстрее работать, так как участки кода с выводом информации не будут работать.
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
@res2001
Developer, ex-admin
Помимо define в плюсах есть и другие инструменты.
Для констант лучше использовать constexpr, для генерации кода шаблоны.
Для define то же есть своя ниша для использования - тот вариант, что вы привели в примере и т.п.
В Си кроме define нет ничего другого. В плюсах есть выбор.
Ответ написан
Комментировать
maaGames
@maaGames
Погроммирую программы
"using namespace std" нежелательно испоьлзвоать в h-файлах, но в cpp-файлах можно пользоваться без угрызений совести. В случае конфликтов можно указывать конкретное пространство, независимо от использованных using. Так же можно использовать using namespace внутри конкретной функции или внутри любого блока кода, ограниченного { }.
Ответ написан
Комментировать
Adamos
@Adamos
За такое использование #define надо клавиатуру отбирать.
Определение макросов только для того, чтобы не написать лишнюю букву, и насрать, как об это будет ломать глаза читающий - классический образец говнокода.

#define - определение переменных времени компиляции. Чтобы просто заменить какую-то величину во всем коде разом - есть константы. Чтобы сократить рутинные повторяющиеся конструкции - свой класс в своем неймспейсе.
#define же позволяет:
- писать программу, которая будет собираться в версии Pro и версии Lite (конкретные блоки кода оборачиваются в #ifdef PRO_VERSION)
- писать кроссплатформенный код, разветвив его по #ifdef __WIN32__ ... #else
и тому подобные возможности управления компиляцией.
Использовать этот механизм для банальных макросов - глупо и опасно. Хотя бы потому, что #define в любом месте кода может переопределить ваше определение совершенно другим значением.
Тем более, что макросы только мешают программисту и IDE понять, что происходит в конкретном месте кода.

Использование #define в библиотеках может быть оправдано, но и там лучше найти способ без него обойтись.
Например, в wxWidgets привязка обработчиков событий со временем прошла вот такую эволюцию:
// В начале, когда Земля была безвидна и пуста, и все ковырялось через макросы
// #define BEGIN_EVENT_TABLE(a,b) wxBEGIN_EVENT_TABLE(a,b)
// #define EVT_PAINT(func) wx__DECLARE_EVT0(wxEVT_PAINT, wxPaintEventHandler(func))
BEGIN_EVENT_TABLE(wxImagePanel, wxPanel)
EVT_PAINT(wxImagePanel::paintEvent)
END_EVENT_TABLE()

// Ближе к цивилизации, макросы еще не вымерли
// #define wxPaintEventHandler(func) wxEVENT_HANDLER_CAST(wxPaintEventFunction, func)
Connect(wxEVT_PAINT, wxPaintEventHandler(paintEvent));

// А что, сразу вот так нельзя было? 
// Bind - метод класса, wxEVT_PAINT - константа, никакой магии...
Bind(wxEVT_PAINT, &wxImagePanel::paintEvent, this);
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы