Windows API и GetClassName ()? Другое имя? - PullRequest
3 голосов
/ 24 февраля 2009

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

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

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

Ответы [ 4 ]

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

Я бы переименовал метод.

Конечно, можно сказать

#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()
2 голосов
/ 24 февраля 2009

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) "для сеттеров. Ваш пробег может отличаться, но я считаю, что он чище, и получение / установка очевидна из аргументов. Очевидно, вы должны быть осторожны, если используете аргументы по умолчанию.

Удачи!

2 голосов
/ 24 февраля 2009

GetWindowClassName возможно? В действительности GetClassName не является плохим именем для этого API, поскольку оно относится к классам окон. Реальная проблема заключается в том, что это объявление C API, и в объявлениях C нет способа ввести повторно используемое объявление, которое не загрязняет глобальное пространство имен.

Это гораздо больше недостаток языка Си, чем Microsoft.

...