Sono uno sviluppatore C incorporato che ha recentemente iniziato a fare scherzi con il codice C++ su un dispositivo embedded e sono sicuri su come const correttezza si applica quando una classe accede ai dati volatili come la memoria registri o dati creati su un dispositivo esterno, ad esempio un convertitore da analogico a digitale (ADC).C++ Const-correttezza con volatili ed esterna dei dati Acess
Ad esempio, devo classi che si interfacciano con moduli hardware del dispositivo accedendo suoi registri mappati nella memoria tramite un puntatore, in questo modo:
class IOPin
{
public:
/* Constructor, destructor, other methods...*/
// should this be a const method?
bool ReadIOState() {return portregs_->state;}
private:
/* Other private stuff...*/
// Constructor points this to the right set of memory-mapped registers
volatile struct portregs_t
{
uint32_t control;
uint32_t state;
uint32_t someotherreg;
} *portregs_;
};
I nomi di registro sono ovviamente costituiti per motivi di esempio. Sto usando un dispositivo Microchip PIC32 per chiunque sia curioso.
Dalla mia possibilmente errata comprensione, contrassegnare un metodo const
significa che lo stato osservabile dell'oggetto non deve cambiare per quanto riguarda il chiamante. Così dovrebbe il metodo ReadIOState()
non essere const
perché accede ai dati volatile
che potrebbe cambiare in qualsiasi momento e in tal modo il chiamante potrebbe osservare il cambiamento? O dovrebbe essere const
perché il metodo non modifica esplicitamente qualcosa?
Attualmente, sto appoggiato verso non facendo che il metodo const
per il motivo indicato nella domanda. Questo è particolarmente vero dopo aver inciampato su this GotW article, che afferma che il significato di const
sta cambiando per significare "in grado di leggere contemporaneamente". La mia applicazione incorporata è single-threaded, ma suppongo che potrebbe essere una buona cartina di tornasole per const
in generale.
Inoltre, come fa il compilatore trattare const
metodi? Cioè, cosa succede quando voglio interrogare lo stato del IO come questo:
// wait for IO pin to go high
while(!myIOpin.ReadIOState())
{}
Se ReadIOState()
è const
, allora il compilatore riutilizzare il valore restituito dopo una chiamata o è abbastanza intelligente per capire che esso sta accedendo ai dati volatile
e non farlo?
Mi chiedo se è possibile creare metodi volatili nello stesso modo in cui è possibile creare metodi const. –
void test() volatile {} compila su VS2012 ma non so cosa significhi visto che non ho mai usato volatile prima. –
@NeilKirk Sì, puoi farlo. Significa che la funzione può essere invocata su un'istanza 'volatile'. Proprio come le funzioni 'const' possono essere invocate su istanze' const'. Puoi anche avere tutti e 4 i sovraccarichi di una funzione membro se ne hai voglia. – Angew