Overload di funzioni basate su const attraverso l'accesso pubblico/protetto
-
23-12-2019 - |
Domanda
(Credo) Conosco le funzioni di sovraccarico basate sulla costanza:se l'istante è const viene chiamato il metodo const, altrimenti quello non-const.
Esempio (anche a ideone):
#include <iostream>
struct S
{
void print() const { std::cout << "const method" <<std::endl };
void print() { std::cout << "non-const method" <<std::endl };
};
int main()
{
S const s1;
s1.print(); // prints "const method"
S s2;
s2.print(); // prints "non-const method"
return 0;
};
Ho provato/provato a utilizzarlo nel mio codice, ma ho riscontrato alcuni problemi quando il file const
i metodi sovraccaricati non hanno la stessa categoria di accesso.Potrebbe essere un cattivo stile, ma ecco un esempio che riflette l'idea di restituire riferimenti per evitare di copiare e utilizzare const
per limitare le alterazioni involontarie:
struct Color;
struct Shape
{
double area;
};
class Geometry
{
public:
// everybody can alter the color of the geometry, so
// they get a mutable reference
Color& color() { return m_color; };
// not everybody can alter the shape of the Geometry, so
// they get a constant reference to the shape.
Shape const& shape() const { return m_shape; };
protected:
// derived classes can alter the shape, so they get
// access to the mutable reference to alter the shape.
Shape & shape() { return m_shape; };
private:
Shape m_shape;
Color m_color;
};
Il problema che sto affrontando ora è che voglio che il compilatore attiri il pubblico, const
-restituendo la funzione di forma se qualche altra funzione interferisce con le Geometrie, diciamo colorarle in base alla loro area, per cui sarebbe necessario accedere alla forma della Geometria:
// this one fails
void colorByArea() {
for( Geometry g : geometryList )
{ g.color() = colorMap[g.shape().area]; }
}
// this one is a clunky workaround
void colorByArea() {
for( Geometry g : geometryList )
{
Geometry const& g_const = g;
g.color() = colorMap[g_const.shape().area];
}
}
Questo (o qualcosa di simile) fallisce con il seguente errore abbastanza comprensibile:
‘Shape& Geometry::shape()’ is protected
Shape & shape() { return m_shape; };
^ error: within this context
g.color() = colorMap[g.shape().area];
(Ho inserito un esempio non compilabile leggermente semplificato su ideone.)
Capisco (in una certa misura) perché questo sta accadendo:g
non è const
e quindi si suppone che venga chiamato il non-const shape(), che è protectedec, ma ovviamente fallisce.
Quindi immagino che il mio DOMANDA È:Esiste un modo per ottenere una sorta di "fallback" su una funzione const se una funzione non const non è accessibile?
Soluzione
Esiste un modo per ottenere una sorta di "fallback" su una funzione const se una funzione non const non è accessibile?
NO;la risoluzione del sovraccarico avviene prima del controllo dell'accesso.
Questo non è solo cattivo stile;è un cattivo design.Una funzione getter pubblica lo è concettualmente diverso da una funzione protetta che consente al codice con conoscenza degli interni di modificare lo stato interno dell'oggetto.In generale non è necessario che le due funzioni abbiano tipi restituiti correlati.Pertanto non dovrebbero avere lo stesso nome.
Altri suggerimenti
Puoi usare const_cast
per consentire di chiamare la versione const come:
int main()
{
S s2;
const_cast<const S&>(s2).print(); // prints "const method"
return 0;
};
Ma sarebbe meglio/più semplice rinominare uno dei metodi.