Wie vermeide ich den Namen Kollision mit Makros, die in Windows -Header -Dateien definiert sind?

StackOverflow https://stackoverflow.com/questions/2321713

  •  22-09-2019
  •  | 
  •  

Frage

Ich habe einen C ++ - Code, der eine Methode nennt CreateDirectory(). Zuvor verwendete der Code nur STL und Boost, aber ich musste kürzlich einbeziehen <windows.h> Also konnte ich nachsehen CSIDL_LOCAL_APPDATA.

Nun, dieser Code:

filesystem.CreateDirectory(p->Pathname()); // Actually create it...

Nicht mehr kompiliert:

error C2039: 'CreateDirectoryA' : is not a member of ...

Das entspricht diesem Makro in winbase.h:

#ifdef UNICODE
#define CreateDirectory  CreateDirectoryW
#else
#define CreateDirectory  CreateDirectoryA
#endif // !UNICODE

Der Pre-Processor definiert meinen Methodenaufruf neu. Gibt es einen möglichen Weg, um diese Namenskollision zu vermeiden? Oder muss ich meine umbenennen CreateDirectory() Methode?

War es hilfreich?

Lösung

Sie werden besser dran sein, wenn Sie Ihre methode erstellte Geräte umbenennen. Wenn Sie Windows -APIs verwenden müssen, ist es ein verlorener Kampf, mit Windows zu kämpfen.

Aufgeben, wenn Sie waren konsistent In einschließlich Windows.h wird dies noch kompiliert. (Obwohl Sie an anderen Orten Probleme haben könnten).

Andere Tipps

Sie könnten ein Modul erstellen, dessen einziger Zweck es ist #include <windows.h> und schauen Sie nach CSIDL_LOCAL_APPDATA, die in eine Funktion eingewickelt sind.

int get_CSIDL_LOCAL_APPDATA(void)
{
    return CSIDL_LOCAL_APPDATA;
}

Übrigens, gut gemacht, um herauszufinden, was passiert ist!

#undEf CreateDirectory

Als Entwickler, der an einer Codesbasis für Cross -Plattform arbeitet, ist dies ein Problem. Die einzige Möglichkeit, damit umzugehen

  • Stellen Sie sicher, dass Windows.h - auf Windows erstellt, mindestens - allgemein eingeschlossen. Dann ist das Makro von CreateDirectory in jedem Ihrer Kompilierungseinheiten definiert und wird allgemein durch CreatedirectoryW ersetzt. Vorkompilierte Header sind dafür ideal

Oder wenn das ein unangenehmes Angebot ist (und es ist für mich)

  • Isolieren Sie Windows.h Nutzung in Windows -spezifische Dienstprogrammdateien. Erstellen Sie Dateien, die die grundlegende erforderliche Funktionalität exportieren. Die Header -Dateien müssen Datentypen verwenden, die kompatibel sind, aber nicht von der Aufnahme von Windows.H abhängen. Die CPP -Implementierungsdatei muss (offensichtlich) Windows.h verwenden.

Wenn Ihre Utlility -Funktionen Projektheader -Dateien mit widersprüchlichen Symbolen enthalten müssen, ist das folgende Muster eine Notwendigkeit:

#include <windows.h>
#ifdef CreateDirectory
#undef CreateDirectory
#endif
// etc
#include "some_class_with_CreateDirectory_method.h"
// ...

Sie müssen dann explizit die Nicht -Makro -Version von Windows -API -Funktionen aufrufen, die Sie #undef'd - erstellteRectorya oder W usw. haben.

push Makro, undef es und pop das Makro wieder:

#pragma push_macro("CreateDirectory")
#undef CreateDirectory
void MyClass::CreateDirectory()
{
 // ...
}
#pragma pop_macro("CreateDirectory")

Beachten Sie, dass der Name Konflikt normalerweise aus einer bestimmten Header -Datei stammt. Bis dahin wird Sachen wie createdirectory und getMessage nicht in Sichtbarkeit und Code kompiliert.

Sie können eine solche Einbeziehung in eine Wrapper -Header -Datei und "#undef was auch immer" am Ende isolieren. Dann wird der Name, den Sie kollision haben, weg sein. Es sei denn natürlich, Sie müssen diese Makros in Ihrem eigenen Code verwenden (ja, also sehr wahrscheinlich...)

Sie können einen Back Up von nehmen CreateDirectory, und definiere es dann und definiere es dann erneut, wenn du deinen Job mit dir beendet hast.

#ifdef CreateDirectory
#define CreateDirectory_Backup CreateDirectory
#undef CreateDirectory
#endif

// ...
// Define and use your own CreateDirectory() here.
// ...

#ifdef CreateDirectory_Backup
#define CreateDirectory CreateDirectory_Backup
#undef CreateDirectory_Backup
#endif
#pragma push_macro("CreateDirectory")

Wenn nichts funktioniert, können Sie anstatt umzubenennen, Sie könnten Ihren eigenen Namespace für Ihre Funktionen verwenden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top