Windows API и GetClassName ()? Другое имя?
У меня есть код, который имеет систему динамических классов на C++, в которой есть член GetClassName (), довольно безобидное имя, которое можно себе представить. Однако при включении в большой проект с заголовками Windows все разразилось адом. По-видимому, Windows использует #define GetClassName (GetClassNameA или GetClassNameW), который все портит, и мое виртуальное дерево вызовов испортилось, из-за чего я потерял день в глупой отладке компилятора в темноте, пытаясь понять, что не так.
Итак, помимо того, что я проклинаю Microsoft за использование такого ужасно легко конфликтующего имени для #define (я имею в виду, что кого-то, честно говоря, за это следует застрелить!), Я прошу трех целей.
- Какое еще хорошее имя для GetClassName ()?
- Есть ли способ исправить это, чтобы в будущем другие разработчики моей кодовой базы не постигли подобную судьбу
- И для потомков, когда кто-то еще сталкивается с этой столь же необъяснимой ошибкой
Ответов (4)4
Я бы переименовал метод.
Конечно можно сказать
#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()
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)». "для сеттеров. Ваш пробег может отличаться, но я считаю, что он чище, и получение / установка очевидна из аргументов. Очевидно, вы должны быть осторожны, если используете аргументы по умолчанию.
Удачи!
Возможно, GetWindowClassName? На самом деле GetClassName - неплохое название для этого API, поскольку он относится к классам окон. Настоящая проблема в том, что это объявление C API, а объявления C не имеют возможности ввести повторно используемое объявление, которое не загрязняет глобальное пространство имен.
Это в большей степени недостаток языка C, чем microsoft.
ClassGetName()
#undef GetClassName
- WinAPI - это C API. Нет пространств имен. Некоторые другие платформы пытаются смягчить это, добавляя префиксы ко всем именам символов, но в конечном итоге это тоже разваливается. Лучший вариант: если вы пишете код , который не зависит от заголовков Windows Platform SDK, то не
#include
их .