Windows API и GetClassName ()? Другое имя?

У меня есть код, который имеет систему динамических классов на C++, в которой есть член GetClassName (), довольно безобидное имя, которое можно себе представить. Однако при включении в большой проект с заголовками Windows все разразилось адом. По-видимому, Windows использует #define GetClassName (GetClassNameA или GetClassNameW), который все портит, и мое виртуальное дерево вызовов испортилось, из-за чего я потерял день в глупой отладке компилятора в темноте, пытаясь понять, что не так.

Итак, помимо того, что я проклинаю Microsoft за использование такого ужасно легко конфликтующего имени для #define (я имею в виду, что кого-то, честно говоря, за это следует застрелить!), Я прошу трех целей.

  1. Какое еще хорошее имя для GetClassName ()?
  2. Есть ли способ исправить это, чтобы в будущем другие разработчики моей кодовой базы не постигли подобную судьбу
  3. И для потомков, когда кто-то еще сталкивается с этой столь же необъяснимой ошибкой

Ответов (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.

  1. ClassGetName()
  2. #undef GetClassName
  3. WinAPI - это C API. Нет пространств имен. Некоторые другие платформы пытаются смягчить это, добавляя префиксы ко всем именам символов, но в конечном итоге это тоже разваливается. Лучший вариант: если вы пишете код , который не зависит от заголовков Windows Platform SDK, то не #includeих .