Domanda

Sto lavorando in C ++ e ho bisogno di sapere se un valore scalare (ad esempio un double) è " definito " o no. Devo anche essere in grado di & Quot; undef & Quot; se necessario:

class Foo {
public:
    double get_bar();

private:
    double bar;
    void calculate_bar() {
        bar = something();
    }
};

double Foo::get_bar() {
    if ( undefined(bar) )
        calculate_bar();
    return bar;
}

È possibile in C ++?

Grazie

È stato utile?

Soluzione

Come dicono le altre risposte, C ++ non ha questo concetto. Puoi facilmente aggirarlo però.

O puoi avere un valore indefinito a cui inizializzi la barra nel costruttore, in genere -1.0 o qualcosa di simile.

Se sai che il calcolo_bar non restituisce mai valori negativi, puoi implementare la funzione indefinita come controllo per < 0.0.

Una soluzione più generale è avere un valore booleano che dice se la barra è stata ancora definita come inizializzata su false nel costruttore e quando la si imposta per la prima volta, la si cambia in vera. boost :: opzionale fa questo in un modo elegante ed elegante.

Ecco come apparirebbe l'esempio di codice che hai.

class Foo {
public:
    double get_bar();
    Foo() : barDefined(false) {}
private:
    double bar;
    bool barDefined;
    void calculate_bar() {
        bar = something();
    }
};

double Foo::get_bar() {
    if ( barDefined == false ) {
        calculate_bar();
        barDefined = true;
    }
    return bar;
}

Altri suggerimenti

Come altri hanno sottolineato, non c'è niente come un " undefined " stato. Ma potresti voler esaminare boost.optional

Se intendi in fase di esecuzione, non esiste nulla del genere. Se bar non viene mai inizializzato, avrà qualsiasi bit casuale presente, a seconda di come viene allocato l'oggetto (alcuni allocatori inizializzeranno la nuova memoria a zero).

modifica: spetta al programmatore gestire lo stato degli oggetti nei costruttori e / o metodi di inizializzazione manuale come init()

Perché non mantenere un flag separato che viene inizializzato su false e quindi impostato su true quando viene calcolata la barra. Può quindi essere "non definito" impostando nuovamente la bandiera su false.

if(!isBarValid)
{
    calculateBar();
    isBarValid = true;
}
return bar;

C ++ non ha un " non definito " stato per tipi primitivi. Il più vicino disponibile per float / double sarebbe NAN, ma questo ha davvero un significato diverso.

Questo non è possibile in C / C ++, le primitive avranno sempre un valore assegnato (principalmente immondizia, qualunque cosa fosse in quel punto in memoria prima di esso, a meno che non fosse esplicitamente assegnato alla dichiarazione). È comune avere un valore segnaposto (ovvero 0 per i puntatori) che indica non utilizzato, tuttavia anche questi devono essere assegnati in modo esplicito. Se il tuo doppio può assumere qualsiasi valore, allora ti suggerisco di mettere un booleano accanto, assegnato inizialmente a false e testare / impostare quello quando vuoi fare il tuo calcolo.

Devi farlo utilizzando un valore booleano aggiuntivo.

Per implementare utilizzando un valore booleano aggiuntivo, è possibile provare la logica come il seguente modello:

template<typename T>
struct Defined
{
 bool defined;
 T value;
 Defined() : defined(false) {}
 Defined(const T& value_) : defined(true), value(value_) {}
 ... and perhaps other operators here ...
 ... to make this behave even more like a T ...
};

Potresti provare Crea al primo linguaggio e scrivi get_bar() in questo modo:

double & get_bar()
{
    static double *bar = new double(something());
    return *bar;
}

Quando chiami bar, double & farà per te se nessuno lo ha ancora chiesto. Eventuali chiamate successive restituiranno semplicemente <=>. Come dice la pagina collegata, questo non perde tecnicamente memoria perché il sistema operativo la rivendicherà alla chiusura del programma.

UPDATE:

Il valore di ritorno è stato modificato in <=> per consentire di modificare <=>.

Inizializza bar su un valore che non può mai verificarsi quando si chiama la funzione something() nel costruttore.

Ad esempio:

Foo(): bar(-1)
{
}

Quindi controlla il valore -1 nella funzione get_bar.

(hmmm Laserallan ha anche pubblicato la risposta 1 minuto prima :-( ;-))

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top