Pregunta

Tengo dos miembros getter:

Node* prev() { return prev_; }
int value()  { return value_ }

Tenga en cuenta la falta de identificadores constantes (los olvidé, pero ahora quiero saber por qué esto no funcionará). Estoy tratando de hacer esto para compilar:

Node(Node const& other) : prev_(other.prev()), value_(other.value()) { }

El compilador rechaza esto. Pensé que C ++ permite la conversión sin const a const en parámetros de función, como:

{
   Foo(int bar);
}

Foo(const int bar)
{
   //lala
}

¿Por qué no me deja hacer lo mismo con un constructor de copias? El identificador const significa que prometo no cambiar nada, entonces, ¿por qué sería importante si obtengo mi valor de una fuente constante o no constante?

¿Fue útil?

Solución

No estás tratando de hacer una conversión sin constante a constante. Está intentando llamar a dos métodos que no son constantes y una referencia constante (llamadas a prev y value). Este tipo de operación está estrictamente prohibido por la semántica constante.

Lo que podría hacer en su lugar es usar los campos prev_ y value_ directamente. Debido a que es un miembro del mismo tipo, puede acceder a elementos privados que estarán disponibles en el objeto const.

Otros consejos

  

Pensé que C ++ permite la conversión sin const a const en parámetros de función, como:

Estás intentando hacer exactamente lo contrario: Const a non-const. Al llamar a una función miembro no constante, el compilador vinculará la expresión (que es un Node const a un Node & amp; para vincular el puntero this ) Por lo tanto, soltará const, no está permitido porque llamaría a una función no const en un objeto const.

/* class Foo */ {
   Foo(int bar);
}

/* Foo:: */ Foo(const int bar)
{
   //lala
}

Bueno, ese código es otra cosa. Declara una función (constructor) dos veces, con la única diferencia de que una vez que el parámetro es constante y otra vez no. El tipo de función es el mismo en ambas ocasiones, por lo que no entran en conflicto (el parámetro const solo tendrá un impacto local dentro del cuerpo de la función; no hará ninguna diferencia para la persona que llama ) Además, este código no contiene ninguna llamada (suponiendo que el primer bloque esté dentro de alguna función).

Si se pregunta: si las dos versiones anteriores son idénticas, ¿por qué no es la siguiente? Entonces esto se debe a que el siguiente contiene otro nivel de indirección: a continuación, la referencia en sí (el nivel superior ) no es constante (no puede poner const en una referencia directamente), pero el tipo al que se hace referencia es const. En este momento, const no se ignora para determinar el tipo de función.

/* class Foo */ {
   Foo(int &bar);
}

// different thing, won't work!
/* Foo:: */ Foo(const int &bar)
{
   //lala
}

Tienes razón: la constante significa que prometes no cambiar nada. El compilador le está haciendo cumplir su promesa al no permitirle llamar a métodos sobre ese objeto que no prometen por sí mismos no cambiar nada.

En la declaración del constructor Node (Node const & amp; other) el argumento other se declara const . Esto significa que solo puede llamar a los métodos const en él.

Está llamando a other.prev () y other.value () desde el constructor, los cuales son métodos que no son const , por lo tanto, el compilador se queja.

Como otros han mencionado, está llamando a métodos no const en un objeto const que el compilador no permitirá.

Una solución simple para esto es marcar sus funciones getter como const:

Node* prev() const { return prev_; }
int value()  const { return value_; }

ya que no modifican el objeto; ahora pueden llamarse con un objeto const. De hecho, esto probablemente debería hacerse de todos modos para que los usuarios de la clase puedan llamar a esos captadores con objetos constantes.

Sin embargo, tiene otro problema potencial en el sentido de que su copiadora se vea así:

Node(Node const& other) : prev_(other.prev()), value_(other.value()) { }

la copia y el original apuntarán al mismo objeto Node en su miembro prev_ . Dependiendo de la semántica de la clase, esto podría estar bien, pero podría ser un problema de propiedad u otra inconsistencia lógica.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top