2009-05-15 47 views
20

estoy en el proceso de creación de una lista ligada doble, y han sobrecargado el operador = para hacer iguales en la lista otra:¿Qué significa "operador = debe ser un miembro no estático"?

template<class T> 
void operator=(const list<T>& lst) 
{ 
    clear(); 
    copy(lst); 
    return; 
} 

pero me sale este error cuando intento compilar:

container_def.h(74) : error C2801: 'operator =' must be a non-static member 

Además, si ayuda, la línea 74 es la última línea de la definición, con el "}".

+0

qué contexto es esto en? en el clase? En toplevel? – bdonlan

+2

Realmente no necesita el lenguaje en el nombre de la pregunta ya que también está etiquetado C++ –

+0

Esta pregunta es engañoso. La pregunta [aquí] (https://stackoverflow.com/questions/5037156/) es más interesante. Aunque la mejor redacción sería "¿Por qué no puede operador = ser global". La respuesta de Johannes Schaub - litb aclara eso. –

Respuesta

17

Exactamente lo que dice: las sobrecargas del operador con 1 parámetro deben ser funciones miembro. (Declara dentro de la clase)

template<class T> 
void list<T>::operator=(const list<T>& rhs) 
{ 
    ... 
} 

Además, es probablemente una buena idea para devolver la LHS de = manera puede encadenar ella (como a = b = c) - de modo que sea list<T>& list<T>::operator=....

+1

Sí, me he dado cuenta: lo declaré en la clase, pero escribí "vacío operador =" en lugar de "lista de vacío operador :: =" –

+13

Lo siento, pero esto es incorrecto. operator = debe ser miembro (como dice el compilador). Lo mismo es cierto para el operador [] y el operador() y posiblemente algunos otros que extraño. Básicamente todos aquellos que tienen que ver con modificar el estado en lugar de producir un valor. Corrija su respuesta y yo retractaré el -1. El problema de Keand64 fue que olvidó especificar la clase (lista :), que no tiene mucho que ver con esta respuesta. –

+0

Oh, oops. Perdón por eso>< –

6

Si sobrecarga un operador como una función miembro, se debe utilizar esta plantilla:

class A { 
    A& operator=(const A& other) { 
    if (this != &other) { 
     ... 
    } 
    return *this; 
    } 
} 

tres cosas a tener en cuenta:

  1. Verifique la autoasignación con el operador de asignación (como se indicó anteriormente);
  2. El argumento debe ser una referencia constante; y
  3. Devuelve el resultado de la operación como una referencia no constante donde devuelve * esto para permitir el encadenamiento de operadores.

También puede sobrecargar un operador externo a la clase. Esto no es relevante para este ejemplo porque no puede hacerlo con el operador de asignación, pero vale la pena señalarlo porque en muchos casos es superior a las funciones de miembro. La forma típica es:

class A { 
    friend const A& operator+(const A& a, const A& b); 
    ... 
} 
const A& operator+(const A& a, const A& b) { 
    A& ret = ... 
    return ret; 
} 

Éste devuelve una referencia constante por lo que no puede hacer esto:

(a + b) = c 
+0

¿Realmente tiene que ser estático? No hay estática funciona bien para mí en g ++. –

+0

Perdón por cruzar los cables. Las funciones que no están dentro de las clases son estáticas por defecto. Puede poner la palabra clave estática pero no es necesaria, así que no hay diferencia, así que la eliminé. – cletus

+0

el operador = debe ser un miembro (lo mismo es cierto para el operador []). Usaría otro ejemplo para mostrar la forma de no miembro. –

18

Ponga ese operador dentro de la definición de clase. Debe ser un miembro porque operator= es especial y de todos modos no ganarías nada escribiéndolo como no miembro. Un operador que no sea miembro tiene dos importantes ventajas principales:

  • conversiones implícitas de la derecha y el lado izquierdo de la invocación del operador
  • No hay necesidad de saber sobre elementos internos de la clase. La función se puede realizar como no miembro no amigo.

Para operator=, ambos no se pueden utilizar. Asignar a un resultado temporal de una conversión no tiene sentido, y operator= necesitará acceso a las partes internas en la mayoría de los casos. Además, C++ proporciona automáticamente un operator= especial si no proporciona uno (el llamado operador de copia de asignación). Posibilitar sobrecargar operator= como no miembro habría introducido una complejidad adicional para aparentemente ninguna ganancia práctica, y eso no está permitido.

Así que cambiar su código para que se parezca a esto (., Esto supone la operator= es no un operador de copia de asignación, pero la asignación de un list<T> a otra cosa Esto no es claro por su pregunta):

class MyClass { 
... 
    template<class T> 
    MyClass& operator=(const list<T>& lst) 
    { 
     clear(); 
     copy(lst); 
     return *this; 
    } 
... 
}; 

Es bastante normal que un operator= devuelve una referencia a sí mismo de nuevo. Te recomiendo que te apegues a esa práctica. Será familiar para los programadores y podría causar sorpresas si devuelve void de repente.

-1

De C++ estándar, "operadores binarios":

"Un operador binario se efectuará bien por una función miembro no estática con un parámetro o por una función no miembro con dos parámetros"

se quiere definir esto en una clase, como miembro, o lo convierten en un método estático (en cuyo caso se debe tomar dos parámetros (tanto para el lval y la rval).

+0

La pregunta original era sobre 'operator =', que no es (según el estándar C++) un "operador binario". Usted citó el párrafo 13.5.2.1. Sin embargo, los operadores de asignación se tratan en la sección 13.5.3: "Un operador de asignación se implementará mediante una función de miembro no estático con exactamente un parámetro ..." – mpb

Cuestiones relacionadas