Windows API и GetClassName()?Другое имя?
-
06-09-2019 - |
Вопрос
У меня есть некоторый код, в котором есть система динамических классов на C ++, в которой есть элемент с именем GetClassName(), довольно безобидное имя, которое можно было бы себе представить.Однако при включении в большой проект с заголовками Windows весь ад вырвался на свободу.Очевидно, Windows использует #define GetClassName (GetClassNameA или GetClassNameW), который все портит, и мое виртуальное дерево вызовов запуталось, из-за чего я потерял день на глупую отладку компилятора в темноте, пытаясь выяснить, что было не так.
Итак, помимо того, что я проклинаю Microsoft за использование такого ужасно легко конфликтующего имени для #define (я имею в виду, что кто-то, честно говоря, должен быть застрелен за это!) Я прошу о 3 целях.
- Какое еще подходящее название для GetClassName() ?
- Есть в любом случае чтобы исправить это, так что в будущем, прочая разработчики из моей базы кода не ждет подобная судьба
- И для потомков, когда кто-то другой столкнется с подобным необъяснимая ошибка
Решение
Я бы переименовал этот метод.
Конечно, можно сказать
#include <windows.h>
#undef GetClassName
но это не чисто, пользователи чьего-либо кода должны помнить, что нужно писать ::GetClassNameW при вызове функции win32.
Можно предоставить методы GetClassNameA и GetClassNameW в своем классе, но это просто некрасиво.
Я вижу два подхода :либо удлините, либо сократите название:)
1) добавьте префикс для всех функций в подсистеме, например TI_ (для получения информации о типе):
TI_GetClassName()
TI_GetBaseClass()
TI_IsDerivedFromClass()
etc
2) или поместить их в какой-нибудь интерфейс iCLASS
interface IClass {
GetName();
GetBase();
IsDerivedFrom();
etc
и верните этот интерфейс из одного метода,
таким образом, функция GetClassName() становится
GetClass()->GetName()
Другие советы
ClassGetName()
#undef GetClassName
- WinAPI - это C-API.Никаких пространств имен.Некоторые другие платформы пытаются смягчить это, добавляя префиксы ко всем названиям символов, но в конечном итоге и это разваливается.Лучший выбор:если вы пишете код, который не зависит от заголовков SDK платформы Windows, тогда не надо
#include
они.
Возможно, GetWindowClassName?На самом деле GetClassName - неплохое название для этого API, поскольку оно относится к оконным классам.Реальная проблема заключается в том, что это объявление C API, а в объявлениях C нет способа ввести повторно используемое объявление, которое не загрязняет глобальное пространство имен.
Это в гораздо большей степени недостаток языка Си, чем Microsoft.
Windows API битком набит макросами с чистыми именами, которые расширяются до имен функций с суффиксом, указывающим ASCII / UTF-16, в зависимости от параметров сборки.Было бы неплохо, если бы они добавляли ко всему префикс "W32" или аналогичный (а-ля "NS" в OS X), но они решили не делать этого, по-видимому, чтобы сохранить API "чистым".
Поскольку изменить ваш код намного проще, чем их API, вот несколько предложений:
1) Изучите Windows API (на самом деле он не такой уж большой!) или, по крайней мере, ознакомьтесь с MSDN чтобы вы могли искать конфликты имен, когда сталкиваетесь с необъяснимым потоком работы программы.
2) Используйте явное разрешение области видимости в своем коде там, где вы можете (MyClass::GetClassName()).К сожалению, это нарушит отправку виртуальных функций, поэтому будьте осторожны с этим.
3) Используйте другое соглашение об именовании в своем коде.MS всегда использует camelCase, поэтому вы не столкнетесь, если выберете какое-то другое соглашение (get_class_name(), GetClassName() и т.д.).
4) Лично я ненавижу называть свои средства получения и настройки "getX ()" и "SetX()", но предпочитаю полагаться на механизм перегрузки и использовать "xtype X() const" для средств получения и "void X (xtype newval)" для средств установки.Ваш пробег может отличаться, но я нахожу его более чистым, и get / set очевиден из аргументов.Очевидно, что вы должны быть осторожны, если используете аргументы по умолчанию.
Удачи вам!