Come rendere la variabile della classe inizializzare solo una volta?

0

Ho una classe chiamata class object che ha una variabile chiamata density (_OMEGA è correlata alla densità: density = _OMEGA * x). Ho anche un file di configurazione (un file txt) dove dico _OMEGA = 1.4. Poi ho letto che _OMEGA e altre variabili di configurazione dal file txt in un contenitore in class config che userò nel mio progetto durante il runtime.

Ora faccio un sacco di questo class object , dato che ne faccio molti non voglio passare _OMEGA a ciascuno di questi oggetti durante la creazione dato che non voglio memorizzare questo _OMEGA in ognuno di questi class object . (Io uso _OMEGA solo per variare la variabile di densità in class object )

So che static variabile è inattiva per questi casi, ma non sono sicuro di come procedere e di usarlo.

  • So che MACRO è inattivo per questo, ma non voglio usarli in questo caso particolare.

Quello che ho fatto finora è:

In main.cpp dopo aver letto il file di configurazione che faccio

object::_OMEGA = config.get_val("OMEGA");

Ricevo un riferimento indefinito all'oggetto :: _ OMEGA

Penso perché ottengo questo errore dal momento che non ho fatto il object::_OMEGA = config.get_val("OMEGA"); nel file cpp. Ma se lo faccio nel file cpp, devo passare il config reference a tutti object class , che sembra controproducente.

Per evitare questo errore ho fatto:

double object::_OMEGA = 0; 

e nel file .h dell'oggetto ho dichiarato una variabile static double _OMEGA

Ora compilo ma ora sono sicuro che questo sia il modo giusto di fare qualcosa.

    
posta solti 08.12.2016 - 19:58
fonte

3 risposte

1

since I make many of them I don't want to pass _OMEGA to each of these object during creation

Non hai davvero scelta. Le altre alternative succhiano molto di più, è solo per un periodo di tempo più lungo.

    
risposta data 08.12.2016 - 20:47
fonte
0

Poiché il valore di Omega deve essere un valore fisso condiviso su tutti gli oggetti, la sensazione istintiva di crearla come statica ha senso. In questo modo non peserai su ogni oggetto con questa variabile. Inoltre, lo stesso può essere ridimensionato per soddisfare una serie di altri dati di configurazione, se necessario.

Puoi limitare la popolazione di Omega a una sola volta utilizzando una macro (come nel codice seguente) o un attributo bool statico che può essere inizializzato a false e successivamente impostato a true nella funzione statica CObject::SetOmega() .

Indipendentemente dal numero di volte in cui chiami CObject::SetOmega() , imposterà il valore solo una volta.

Poiché la classe Config non era in discussione, ho inserito alcune definizioni funzionali nel file .h per brevità di risposta qui.

CObject.h .

#ifndef COBJECT_H
#define COBJECT_H
#define UNPOPULATED_OMEGA -1
class CObject
{
    static float s_mOmega;
    float mDensity;
public:
    CObject(int dnstFactor);
    static void SetOmega(float omega);
    static float GetOmega();
    float GetDensity()const;
};
#endif //COBJECT_H

. .

CObject.cpp .

#include "CObject.h"                              

float CObject::s_mOmega = UNPOPULATED_OMEGA;

CObject::CObject(int dnstFactor)
{
    mDensity = s_mOmega * dnstFactor;
}

void CObject::SetOmega(float omega)
{
    if(s_mOmega == UNPOPULATED_OMEGA)
        s_mOmega = omega;
}

float CObject::GetOmega()
{
    return s_mOmega;
}

float CObject::GetDensity()const
{
    return mDensity;
}

. .

Config.h .

#ifndef CCONFIG_H
#define CCONFIG_H
#include <iostream>
#include <string>

class Config
{
public:
    Config(const char* configFileName)
    {
        std::cout << "Loading from file " << configFileName << std::endl;
    }

    float get_val(const std::string& key)
    {
        if (!key.compare("OMEGA"))
            return 1.4f;
    }
};
#endif //CCONFIG_H

. .

main.cpp .

#include <iostream>
#include "Config.h"
#include "CObject.h"

using namespace std;

int main()
{
    Config config("config.txt");
    CObject::SetOmega(config.get_val("OMEGA"));

    CObject obj1(10);
    cout << "Obj1 --> " << obj1.GetDensity() << endl;

    CObject obj2(10);
    cout << "Obj2 --> " << obj2.GetDensity() << endl;

    CObject::SetOmega(100);

    CObject obj3(10);
    cout << "Obj3 --> " << obj3.GetDensity() << endl;

    CObject::SetOmega(200);

    CObject obj4(10);
    cout << "Obj4 --> " << obj4.GetDensity() << endl;

    return 0;
}
    
risposta data 14.12.2016 - 11:24
fonte
0

Quindi hai bisogno di questo valore durante l'istanziazione delle tue classi.

Ecco la cosa più semplice che potresti fare . Passa la tua configurazione dall'alto nel grafico delle dipendenze e utilizzalo quando crei le tue classi . (Userò pseudo codice, il mio punto è abbastanza indipendente dal linguaggio):

class Foo {
    Foo(config Config){
       _config = config; // I'm assuming your have an object which encapsulates your config?
    }

    DoSomething() {
        var myobject = new MyObject(_config.omega);
        ....
    }
};

In alternativa, un pattern che puoi usare per consentire alla classe Foo di creare un oggetto MyObject senza conoscere le sue (potenzialmente molte) dipendenze è il modello di fabbrica :

class Foo {
    Foo(myObjectFactory MyObjectFactory){
       _myObjectFactory = myObjectFactory; 
    }

    DoSomething() {
        var myobject = myObjectFactory.Create();
        ....
    }
};

class MyObjectFactory {
    MyObjectFactory(config Config) {
        _config = config;
    }

    Create() {
        return new MyObject(_config.omega);
    }
}

L'utilizzo di una factory è probabilmente eccessivo in questo caso, poiché MyObject ha solo una dipendenza, ma può essere utile per le classi con più dipendenze, che quindi hanno le loro dipendenze ecc. ecc.

Quindi ti consiglio di iniziare con il wrapping della tua configurazione in una classe Config e di passarla agli oggetti Foo -like, come nel mio primo esempio. Questa classe di configurazione non dovrebbe essere un singleton, ma è ragionevole crearla una sola volta (molto in alto nell'albero delle dipendenze, o nel tuo contenitore DI se ne hai una), e rendere i suoi valori pigri o inizializzati nel suo costruttore.

Non usare oggetti di Dio, statici e globali. Questi rendono il codice difficile da ragionare, difficile da separare e impossibile da rendere sicuro.

    
risposta data 14.12.2016 - 12:09
fonte

Leggi altre domande sui tag