2012-03-05 20 views
5

He una clase que contiene un mapaoperador sobrecargado no lanzar excepciones

Any& Map::operator[](const unsigned int field) const 
{ 
    try 
    { 
    iterator it; 
    if ((it = m_fields.find(field)) != m_fields.end()) 
     return it->second; 

    throw std::runtime_error("Field " + boost::lexical_cast<std::string>(field) + " not found."); 
    } 
    catch(boost::bad_any_cast&) 
    { 
    throw std::runtime_error("Failed conversion field " + boost::lexical_cast<std::string>(field) + " using boost::any_cast "); 
    } 
} 

lo quiero para lanzar una excepción cuando el campo no existe en el mapa para que el programa no se cuelga en un mal get, pero el lanzamiento no parece funcionar en el operador sobrecargado, el programa se bloquea de todos modos, por lo que se ignoran el lanzamiento o la captura. Si utilizo el mismo código pero con una función común

Any& Map::get(const unsigned int field) const 
{ 
    //... 

funciona.

¿Funcioné en alguna limitación C++ o estoy haciendo algo mal?

--edit:

me encontré con el depurador y para mi sorpresa que el código ni siquiera ejecutar, otro método no

Any& Map::operator[](const unsigned int field) 
{ 
    iterator it; 
    if ((it = m_fields.find(field)) == m_fields.end()) 
    { 
    Any newValue; 
    m_fields[field] = newValue; 
    return m_fields[field]; 
    } 

    return it->second; 
} 

y el accidente se produce debido a un impulso de afirmar Cualquiera que intente convertir una variable no inicializada. Este método se utiliza probablemente de inserciones en el mapa, como

Map a; 
a[3] = "foo"; 

Así que supongo que no tengo manera de diferenciar cuando se utiliza el operador en una teoría de la atribución o en un get y el uso de este operador es altamente peligroso para obtiene

+0

Personalmente me gustaría poner el 'find' y la comparación de diferentes líneas – pkit

+1

Es (probablemente) no sea la causa de su problema, pero tendrá que devolver por valor: no puede devolver una referencia a un temporal. –

+0

@pkit Y inicializar 'it' en la declaración que lo definió. –

Respuesta

2

Re la edición: la resolución de sobrecarga generalmente solo tiene en cuenta los argumentos , no el uso. Si tiene una función const y una función sin const. con firmas idénticas de lo contrario, se elegirá la no const si es posible (por ejemplo, invocando un objeto no const).

En caso de que desee un comportamiento diferente según el uso, la solución tradicional es proporcionar un proxy. Su clase Map sería contener dos funciones get y set, y la no-const operator[] devolvería un proxy que será similar a:

class Proxy // member of Map 
{ 
    Map* myOwner; 
    int myIndex; 
public: 
    Proxy(Map* owner, int index) 
     : myOwner(owner) 
     , myIndex(index) 
    { 
    } 
    void operator=(Any const& rhs) const 
    { 
     myOwner->put(myIndex, rhs); 
    } 
    operator Any() const 
    { 
     return myOwner->get(myIndex); 
    } 
}; 
+0

+1 para el proxy. El "patrón" de "Proxy" a menudo no se tiene en cuenta, aunque probablemente sea uno de los patrones más volátiles que he visto. –

Cuestiones relacionadas