Как работает препроцессор C ++
В случае #define A B
препроцессор заменяет ВСЕ вхождения A
на B
.Это чистая замена.
Будет ли мой проект вызывать SendMessage
или SendMessageA
?
Ваш проект будет вызывать либо SendMessageA
, либо SendMessageW
- в зависимости отбыл ли он скомпилирован с поддержкой Unicode или нет.Нет функции SendMessage
- она не существует.
f если произведена замена, проект не должен компилироваться.
SendMessageA объявлено в <widnows.h>
(или в заголовке, который включен из windows.h) - где-нибудь, и его информация о связывании находится в одной из библиотек базовой системы (я думаю, User32.lib).Если вы работаете в Windows, очень вероятно, что <windows.h>
где-то #included
, и соответствующий * .lib уже находится в зависимостях компоновщика.
- EDIT -
Более конкретный вопрос: препроцессор вслепую заменяет определения?
Да, препроцессор вслепую заменяет определения.Для не слепой замены у вас есть шаблоны, но у них есть свои ограничения.Что-то, что можно сделать с помощью препроцессора, нельзя сделать с помощью шаблонов и наоборот.В препроцессоре есть оператор stringize, в шаблонах есть проверка типов и метапрограммирование.
Моя проблема в том, почему иногда вызывается функция-член SendMessage, потому что код работает (большую часть времени)
Если у вас есть SendMessage
метод в вашем коде (идея ПЛОХО на платформе Windows - конфликтует с системным макросом, замените на sendMessage()
или используйте другое имя, потому что даже пространства имен не помогут вам избежать вездесущего препроцессора) ваш метод (не SendMessageA
/ SendMessageW
) будет вызываться ТОЛЬКО из * .cpp, если <windows.h>
не было включено в этот * .cpp.
Компилятор работает с одним файлом за раз и не знает, что происходит в других файлах, поэтому, если нет <windows.h>
#included
, , будет вызван ваш метод потому что препроцессор не будет знать о SendMessage
#define
(из <windows.h>
).Если включено <windows.h>
, то ВСЕ вхождения SendMessage
будут заменены на SendMessageA
/ SendMessageW
, потому что препроцессор сначала выполняет свою работу.
Одним из возможных решений в вашей ситуации было бы избегать использования соглашения об именовании, аналогичного соглашению в Win API.Т.е. убедитесь, что имена функций не начинаются с заглавной буквы.Это решит многие проблемы, но вы все равно получите небольшие проблемы с min
/ max
макросами.