[C++] Define in anderer CPP prüfen

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
Benutzeravatar
Zudomon
Establishment
Beiträge: 2253
Registriert: 25.03.2009, 07:20
Kontaktdaten:

[C++] Define in anderer CPP prüfen

Beitrag von Zudomon »

Die ersten Zeilen meiner Haupt-CPP hat folgende Includes:

Code: Alles auswählen

#include "Extern/gl3w.h"
#include <GL/GL.h>
#include <iostream>
#pragma comment (lib, "opengl32.lib")

#define DEBUG_MOUSE

#include "resource.h"
#include "uBasic.h"
#include "uWin.h"
Also zunächst werden die offiziellen eingebunden, danach meine. Allerdings füge ich dazwischen noch das "#define DEBUG_MOUSE" ein. Nun habe ich erwartet, dass ich in der uWin.cpp auf dieses Define entsprechend zugreifen kann. Das funktioniert aber nur, wenn sich das Define in der uWin.h befindet. Ich dachte ja, dass der Code einfach eingefügt wird.

Oh, Moment. Wo ich das jetzt schreibe wird mir klar, dass ich eventuell einen Denkfehler habe. Wird jetzt erstmal jede CPP für sich übersetzt und als Quellcode durch das Include nur der Code der Header rein kopiert? Dann kennt die uWin.cpp natürlich nicht die Haupt-CPP und damit das Define auch nicht. Falls das der Grund ist, wie wird sowas dann gelöst?

In der uWin.cpp sollte es so aussehen:

Code: Alles auswählen

if (!(CursorActive && UseHWCursor)) {
#ifndef DEBUG_MOUSE
	SetCursor(0);
#endif	
	return result;
}
Ich hätte halt gerne, dass ich von meiner Haupt-Cpp aus die Defines setzen kann.
Benutzeravatar
Jonathan
Establishment
Beiträge: 2352
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: [C++] Define in anderer CPP prüfen

Beitrag von Jonathan »

Nein, defines musst du schon in Header setzen. Es werden ja die Header inkludiert, nicht die cpp's.

Was aber Sinn machen würde, wäre etwa eine global.hpp die die defines definiert und dann überall eingebunden wird, wo man sie braucht. Überhaupt willst du damit sehr sparsam umgehen, es ist immer mega unübersichtlich, wenn die eine Stelle im Code darüber entscheidet, was die andere macht. Alleine deshalb wäre es schon gut, alle defines an einer zentralen Stelle zu haben anstatt über mehrere Dateien verstreut.
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
NytroX
Establishment
Beiträge: 358
Registriert: 03.10.2003, 12:47

Re: [C++] Define in anderer CPP prüfen

Beitrag von NytroX »

Ja, das Problem ist, dass jede cpp-Datei eine einzelne Übersetzungseinheit bildet.
Und die wissen alle nix voneinander.
Später versucht dann der Linker, einen Sinn darin zu finden und die deklarierten aber nicht definierten Symbole/Funktionen durch andere Übersetzungseinheiten aufzulösen.

Lösen tut man das mit durchdachtem Dependency-Management
Versuch die includes so gering wie möglich zu halten und nur im cpp zu verwenden.
Außer es ist unbedingt im interface notwendig.

Code: Alles auswählen

#include "Extern/gl3w.h"
#include <GL/GL.h>
=> gehören vermutlich beide zum renderer, haben in der main nix zu suchen

#include <iostream>
=> gehört wahrscheinlich zum ResourceManager irgendwo
Man kann für so ganz allgemeine Sachen (string, globale #defines) eine "common.h" oder so nehmen, wie Jonathan vorgeschlagen hat, und die von überall aus einlesen.

Aber dein #define DEBUG_MOUSE ist generell eher nicht so geil, weil man den Preprocessor für sowas nicht braucht. Schreib das doch lieber in C++.
Wie wärs z.B. stattdessen mit einer globalen Konfiguration?

Code: Alles auswählen

//common.h
namespace Configuration {
	static constexpr bool DEBUG_MOUSE = true;
}

//uWin.h
#include "common.h"
if (!(CursorActive && UseHWCursor)) {
  if constexpr (!Configuration::DEBUG_MOUSE){
	SetCursor(0);
  }
  return result;
}
Spiele Programmierer
Establishment
Beiträge: 426
Registriert: 23.01.2013, 15:55

Re: [C++] Define in anderer CPP prüfen

Beitrag von Spiele Programmierer »

Noch paar Denkanstöße:
  • Die beiden Vorredner haben bereits eine globale Datei mit allen möglichen solchen Einstellungen vorschlagen. Ich möchte dazu noch zu bedenken geben: Wenn du dies machst, musst bei der Änderung jeder Einstellung praktisch alles neukompilieren. Das hängt natürlich sehr vom Anwendungsfall ab, aber wenn du DEBUG_MOUSE z.B. nur irgendwo in der Fenster-Verwaltung brauchst, kann es sehr nervig sein, erstmal ein paar Minuten rumzukompilieren, nur um die Maus zu debuggen. Deshalb würde ich im Prinzip tendentiell das Gegenteil vorschlagen und die #defines so lokal wie möglich platzieren. Am besten oben in der betroffenen *.cpp-Datei. Dann darfst du das aber natürlich auch nur in dieser Datei verwenden. Meiner Meinung nach erhöht das aber die Modularisierung/Überisicht, da du jetzt sicher weißt, dass dieses #define nur in dieser Datei etwas verändert. Wenn du ein globales #define machst, kann das ja überall etwas ändern.
  • Nytrox hat recht damit, dass es oft besser ist, gar nicht erst ein #define zu verwenden. Mach stattdessen am besten eine normale Variable wie in anderen Programmiersprachen. Ich würde ein #define nur verwenden, wenn das unvermeidbar ist, also z.B. wenn dadurch zusätzliche Abhängigkeiten (spricht #includes) hinzukommen, die man nur mit #if bei der normalen Kompilierung komplett ausschließen kann. Das ist bei plattformabhängigen Codepfaden ja oft der Fall.

    Ich würde für normale globale Konstanten allerdings von den Großbuchstaben absehen. Da der Präprozessor wirklich alles ersetzt was ihm in die Finger kommt, kann es unangenehme Überraschungen geben. Wenn du nur genau das in Großbuchstaben setzt, was für den Präprozessor bestimmt ist, kann das nicht passieren. windows.h ist z.B. ja immer ein besonderer Spaß, denn das ersetzt dir gerne so einiges in deinem Code mit ihren eigenen #defines.
  • Wenn du eine globale Konfiguration machst, würde ich vorschlagen, die Variablendefinition in eine *.cpp-Datei auszulagern. Also so:

    Code: Alles auswählen

    //Config.h
    
    extern const bool DebugMouse;
    Und dann:

    Code: Alles auswählen

    //Config.cpp
    
    const bool DebugMouse = true;
    Dadurch vermeidest du das Problem, dass alles Neukompiliert werden muss, wenn du eine Einstellung änderst. Nachteil ist, dass der Compiler den nicht genommenen Codepfad ggf. nicht wegoptimieren kann (und wenn dann, nur mit LTO also Linkzeit-Optimierungen).

    Ob das besser ist, hängt wieder vom Anwendungsfall ab, aber für Maus-Debugging klingt das für mich sinnvoll.
Benutzeravatar
Zudomon
Establishment
Beiträge: 2253
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: [C++] Define in anderer CPP prüfen

Beitrag von Zudomon »

Danke für die ausführlichen Infos! :D
Zugegeben, bei DEBUG_MOUSE ist das vielleicht Kanonen auf Spatzen. Aber ich möchte das Konzept hinterher an einigen Stellen einbauen und deswegen schon zu Beginn wissen, welche Strategien es da gibt. Ihr habt ja nun schon Anregungen gegeben.

NytroX hat geschrieben: 14.03.2021, 16:41 #include "Extern/gl3w.h"
#include <GL/GL.h>
=> gehören vermutlich beide zum renderer, haben in der main nix zu suchen
Aktuell gibt es noch nicht viel mehr als die Haupt-CPP :D

Ich würde mich dann wohl am ehesten doch für das lokale Define entscheiden.
Antworten