Devo inserire #define in un file separato?

-1

Ho pensato a due tecniche per il mio #define :

Tecnica 1

SomeClass.h:

#define SOME_BUFFER_LENGTH 256

class SomeClass {
  /* ... */
}; 

Tecnica 2

config.h:

#define SOME_BUFFER_LENGTH 256
#define SOME_OTHER_THING_USED_ELSEWHERE 23

SomeClass.h:

#include "Config.h"

#ifndef SOME_BUFFER_LENGTH
  #define SOME_BUFFER_LENGTH <Default Value>
#endif

class SomeClass {
  /* ... */
};

Quali sono i pro e i contro di questi due metodi e oggettivamente per un grande progetto, quale è il migliore?

Modifica

Ciao, ho imparato due cose dai tuoi commenti e risposte:

@gnasher729: If there might be reasons to change it to a different value, then it's bad if you have to hunt down such constants in many different source files, but better to have it in a configuration file with the express intent to configure things.

e

@Phil1970: Better to use C++ constants instead of the processor.

Quindi termino con questo comportamento:

config.h:

namespace Config {
  const type constant = value;
  const type anotherconstant = anothervalue;
}

SomeClass.h:

#include "Config.h"
/* ... */
void somefunc() {
  usefulfunc(Config::constant, /* ... */);
}

Penso che sia perfettamente adatto per un progetto OpenSource, sto aspettando il tuo punto di vista su questo!

    
posta Nurrl 26.08.2017 - 16:04
fonte

2 risposte

6

Dipende. Ti serve #define per evitare le "costanti magiche" o usi il #define per renderlo configurabile?

Se SOME_BUFFER_LENGTH deve essere 256, e non vuoi scrivere 256 ovunque nel tuo codice sorgente, tienilo nel file sorgente. Se ci potrebbero essere dei motivi per cambiarlo in un valore diverso, allora è brutto se si devono cercare costanti di questo tipo in molti file sorgente diversi, ma è meglio averlo in un file di configurazione con l'esplicito intento di configurare le cose.

A proposito. Il metodo "#ifndef" ha il grande svantaggio che il risultato potrebbe dipendere dall'ordine in cui si includono i file di intestazione o se li si include del tutto. Diciamo che ho due file che contengono quanto segue:

#ifndef SOME_BUFFER_LENGTH
    #define SOME_BUFFER_LENGTH 256
#endif

e

#ifndef SOME_BUFFER_LENGTH
    #define SOME_BUFFER_LENGTH 1024
#endif

La modifica dell'ordine in cui si includono i file di intestazione modifica il valore. Peggio ancora, se due file sorgente li includono in ordini diversi, non saranno d'accordo sul valore. Ora immagina che abbiano entrambi una struct con un membro "char buffer [SOME_BUFFER_LENGTH];". Sei nei guai.

    
risposta data 26.08.2017 - 17:45
fonte
2

Dipende se SOME_BUFFER_LENGTH è usato solo in una classe / file, o deve essere disponibile in posti diversi. In quest'ultimo caso, aderire alla regola SPOT e spostarli su un'intestazione comune può farti risparmiare molti mal di testa.

BTW, in C ++ ci sono modi migliori rispetto all'uso di definizioni / macro di tipo non sicuro:

//Anonymous enum constant
enum
{
    SomeBufferLength = 256
}

//Named enum constant (C++11, type-safe)
enum class BufferLength : size_t
{
    SomeBuffer = 256
}

//Anonymous namespace (replaces local static variables/constants)
namespace
{
    const size_t SomeBufferLength = 256;
}

Le enumerazioni possono essere parte dell'interfaccia pubblica o privata della classe in cui vengono utilizzate (o dove dovrebbero risiedere quando si aderisce alla corretta progettazione OO) a condizione che tutti i metodi che li accedono possano includere la dichiarazione. E lo spazio dei nomi anonimo è valido solo nel file di codice locale, puoi applicarlo se è garantito che non venga usato da nessun'altra parte.

    
risposta data 28.08.2017 - 17:28
fonte

Leggi altre domande sui tag