2009-08-17 24 views
5

Ho questo frammento di codice qui. L'intenzione è di fare una copia di initialData. Dal momento che non sto modificando initialData in alcun modo, immagino che dovrei passarlo come riferimento const. Tuttavia, continuo a ricevere questo messaggio durante la compilazione.C++ e const-accesso a una funzione membro di un riferimento const

\ src \ Scene \ SceneAnimationData.cpp (23) :. Errore C2662: 'SceneTrackerData :: getRect': non può convertire puntatore 'this' da '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); 
} 

risposta

13

senza la definizione di SceneTrackerData, è difficile da dire, ma probabile che la funzione (SceneTrackerData::getRect) non è contrassegnato come const.

Questo è, ciò che è (indovinare):

const Rect& SceneTrackerData::getRect(void) 

dovrebbe essere:

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

una domanda - non const per getRect (void) implica che non posso cambiare Rect? So che il compilatore non può "vedere" questo - ma la mia ipotesi è che non tutti i metodi di Rect sono const. Senza che tutti siano costanti, non puoi fare affidamento su getRect senza modificare Rect. Sarebbe più chiaro (in questo caso) gettare via la costanza nell'altra funzione invece di aggiungerla qui? –

+1

Fintanto che getRect non chiama nessuno degli altri metodi non-const di Rect, o esegue altre modifiche, getRect può garantire che non modifica il Rect. Ciò significa che posso chiamare getRect su un oggetto const Rect - tuttavia, ci sarebbe un errore di compilazione se provassi a chiamare un altro metodo non const sullo stesso oggetto. Ecco come viene preservata la costanza: avendo le chiamate al metodo non const falliscono, mentre le chiamate al metodo const sono permesse. – GRB

1

Non è chiaro che è la linea 23 qui; ma suppongo che tu stia chiamando metodi sull'oggetto che non sono dichiarati come const e quindi non sono utilizzabili da un riferimento all'oggetto const.

1

Non sono sicuro perché non sono un programmatore C++ esperto, ma le funzioni sono getRect() e così via const dichiarato? In caso contrario, se si conosce il modo in cui li si utilizza è const, è comunque possibile utilizzare un const_cast per rimuovere il const dal riferimento initialData.

Si veda ad esempio qui: http://docs.oracle.com/cd/E19422-01/819-3690/Cast.html

O Scott Meyers eccellente C++ - Libri Effective C++ e More Effective C++. Almeno uno di loro ha un oggetto sulla costanza.

linee
1

sto pensando come questi sono illegali:

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

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

in quanto il passato in links e points non sono definiti come puntatori, ma valori definiti. Al fine di compilare il codice, probabilmente è necessario a uno di loro di definire in questo modo

const QList<QGraphicsLineItem*>* links 

o, invece li usano come questo

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

tuttavia che quest'ultima sia potenzialmente un errore di run-time, perché stai accedendo all'indirizzo di un valore temporaneo, che muore dopo il corpo della funzione.

A meno che QList non usi una copia profonda, è probabile che l'app si arresti in modo anomalo.

+0

Grazie. Mi hai aiutato a rintracciare altri 2 bug! – Extrakun

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

Questo potrebbe essere potenzialmente legale se l'operatore * è sovraccarico per la classe QList, anche se non penso che lo sia.Anche se, come già detto, probabilmente stai cercando di fare

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

A seconda di ciò che richiede il costruttore effettivo.

Inoltre, ciascuna di queste funzioni deve prendere in QList per riferimento, per motivi di prestazioni. In questo momento si copia l'intero oggetto due volte per ogni volta che si chiama la funzione. Una volta per passare in valore, quindi una volta per la costruzione della copia.

Una cosa da ricordare quando si ha a che fare con const'ness è che const non è garantito. Esistono strutture come "const_cast" per rimuovere la costanza di un oggetto. Avere un oggetto const e usare le funzioni const è utile per indicare ad altri sviluppatori che il codice non deve cambiare l'oggetto, non che sia non possa cambiare lo. Vedi la differenza?

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 utile è che i tentativi intenzionali per modificare l'oggetto si tradurrà in errori di compilazione, un programmatore determinato può facilmente aggirare queste protezioni.

Problemi correlati