2009-08-17 8 views
5

Tengo este fragmento de código aquí. La intención es hacer una copia de initialData. Como no estoy modificando initialData de ninguna manera, creo que debería pasarlo como una referencia constante. Sin embargo, sigo recibiendo este mensaje al compilar.C++ y const - accediendo a una función miembro de una referencia de referencia

\ src \ Escena \ SceneAnimationData.cpp (23) :. Error C2662: 'SceneTrackerData :: getRect': no ​​se puede convertir este puntero de 'const SceneTrackerData' a 'SceneTrackerData &'

#include "SceneTrackerData.h" 

void SceneAnimationData::SetupData(const SceneTrackerData &initialData) 
{ 
    // getRect(), points() and links() all return const pointers 
    CloneRect(initialData.getRect()); 
    ClonePoints(initialData.points()->values()); 
    CloneLinks(initialData.links()->values()); 
} 

void SceneAnimationData::CloneRect(const QGraphicsRectItem * initialRect) 
{ 
    if (initialRect != NULL) 
    { 
     QPointF position = initialRect->scenePos(); 
     QRectF rect = initialRect->rect(); 

     initialRect = new QGraphicsRectItem(rect); 
     initialRect->setPos(position); 
    } 
} 

void SceneAnimationData::CloneLinks(const QList<QGraphicsLineItem*> links) 
{ 
    links_ = new QList<QGraphicsLineItem*>(*links); 
} 

void SceneAnimationData::ClonePoints(const QList<QGraphicsEllipseItem*> points) 
{ 
    points_ = new QList<QGraphicsEllipseItem*>(*points); 
} 

Respuesta

13

sin la definición de SceneTrackerData, que es difícil de decir, pero es probable que la función (SceneTrackerData::getRect) no está marcado como const.

Es decir, lo que se (adivinar):

const Rect& SceneTrackerData::getRect(void) 

debe ser:

const Rect& SceneTrackerData::getRect(void) const 
         //     ^
         //      | 
         // does not logically modify the object 
+0

una pregunta - no const para getRect (void) implica que no puedo cambiar Rect? Sé que el compilador no puede "ver" esto, pero supongo que no todos los métodos de Rect son const. Sin todos ellos const, no puede confiar en que getRect no cambie el Rect. ¿Sería más claro (en este caso) desechar la constness en la otra función en lugar de agregarla aquí? –

+1

Siempre que getRect no llame a ninguno de esos otros métodos no const de Rect, o haga cualquier otra modificación, getRect puede garantizar que no modifica el Rect. Eso significa que puedo llamar a getRect en un objeto const Rect; sin embargo, habría un error de compilación si intentara llamar a otro método no const en el mismo objeto. Así es como se preserva la constness: al hacer fallar las llamadas al método non-const, mientras que las llamadas al método const están permitidas. – GRB

1

No está claro que es aquí la línea 23; pero supongo que está llamando métodos al objeto que no están declarados como const y, por lo tanto, no se pueden usar con una referencia de objeto const.

1

No estoy seguro ya que no soy un experto programador de C++, pero ¿son tus funciones getRect() y así sucesivamente declaradas const? Si no, pero sabes que la forma en que los usas es const, aún puedes usar un const_cast para eliminar la const de tu referencia de datos iniciales.

Véase, por ejemplo aquí: http://docs.oracle.com/cd/E19422-01/819-3690/Cast.html

O Scott Meyers excelente C++ - Libros Effective C++ y More Effective C++. Al menos uno de ellos tiene un elemento sobre constness.

líneas
1

estoy pensando como estos son ilegales:

links_ = new QList<QGraphicsLineItem*>(*links); 

points_ = new QList<QGraphicsEllipseItem*>(*points); 

en que la aprobada en links y points no están definidos como punteros, pero los valores definidos. Para compilar el código, es probable que tenga que sea definirlas como esto

const QList<QGraphicsLineItem*>* links 

o, en su lugar utilice como esto

links_ = new QList<QGraphicsLineItem*>(&links); // don't actually do this 

Sin embargo, la última es potencialmente un error en tiempo de ejecución, porque está accediendo a la dirección de un valor temporal, que muere después del cuerpo de la función.

A menos que QList utilice una copia profunda, es muy probable que su aplicación falle.

+0

Gracias. ¡Me has ayudado a rastrear 2 errores más! – Extrakun

0
links_ = new QList<QGraphicsLineItem*>(*links); 

Esto podría ser legal si el operador * está sobrecargado para la clase QList, aunque no creo que es.Aunque como se mencionó anteriormente, es probable que tratar de hacer

links_ = new QList<QGraphicsLineItem*>(links); 

Dependiendo de lo que lleva el constructor real.

Además, cada una de esas funciones debería tener en cuenta la QList por referencia, por razones de rendimiento. En este momento, copia el objeto completo dos veces por cada vez que llama a la función. Una vez para pasarlo por valor, luego una vez para la construcción de la copia.

Una cosa para recordar cuando se trata de la const'ness es que const no está garantizada. Existen estructuras como "const_cast" para quitar la consistencia de un objeto. Tener un objeto const y usar funciones const es útil para indicar a otros desarrolladores que el código no debe cambiar el objeto, no que no puede cambiar. ¿Ver la diferencia?

void bar(const Foo& f) { 
    f.setX(5); // compile error, f is const 
    Foo &f2 = const_cast<Foo&>(f); 
    f2.setX(5); // compiles just fine 
} 

la parte útil es que los intentos no intencionales para cambiar el objeto dará lugar a errores de compilador, un programador determinado puede eludir fácilmente estas protecciones.

Cuestiones relacionadas