tags:

views:

524

answers:

5

I have this snippet of code here. The intention is to make a copy of initialData. Since I am not modifying initialData in any way, I figure that I should pass it as a const reference. However, I keep getting this message when compiling.

.\src\Scene\SceneAnimationData.cpp(23) : error C2662: 'SceneTrackerData::getRect' : cannot convert 'this' pointer from 'const SceneTrackerData' to '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);
}
+8  A: 

Without the definition of SceneTrackerData, it's hard to say, but likely that function (SceneTrackerData::getRect) is not marked as const.

That is, what is (guessing):

const Rect& SceneTrackerData::getRect(void)

Should be:

const Rect& SceneTrackerData::getRect(void) const 
                        //                     ^
                        //                     |
                        // does not logically modify the object
GMan
one question - doesn't const for getRect(void) imply that I can not change Rect? I know the compiler can't "see" this - but my guess is that not all methods of Rect are const. Without all of them being const, you can not rely on getRect not changeing the Rect. Would it be clearer (in this case) to cast away constness in the other function instead of adding it here?
Tobias Langner
As long as getRect does not call any of those other non-const methods of Rect, or do any other modifications, then getRect can guarantee that it does not modify the Rect. That means that I can call getRect on a const Rect object -- however, there would be a compile error if I tried to call another non-const method on the same object. That's how constness is preserved: by having non-const method calls fail, while const method calls are allowed.
GRB
+1  A: 

It's not clear which is line 23 here; but my guess is that you are calling methods on the object that are not themselves declared as const and thus are not usable by a const object reference.

Steve Gilham
+1  A: 

I'm not sure as I am no expert C++ programmer, but are your functions getRect() and so on declared const? If not but you know the way you use them is const, you can still use a const_cast to remove the const from your initialData reference.

See for example here: http://docs.sun.com/source/819-3690/Cast.html

Or Scott Meyers excelent C++-Books "Effective C++" and "More Effective C++". At least one of them has an item about constness.

Tobias Langner
+1  A: 

I am thinking lines like these are illegal:

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

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

in that the passed in links and points are not defined as pointers, but defined values. In order to compile the code, You probably need to either define them like this

const QList<QGraphicsLineItem*>* links

or, instead use them like this

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

However the latter one is potentially a run-time bug, because you are accessing the address of a temp value, which dies after the function body.

Unless QList uses a deep-copy, your app may very likely crash.

t.g.
Thanks. You've helped me to track down 2 more bugs!
Extrakun
A: 
links_ = new QList<QGraphicsLineItem*>(*links);

This could potentially be legal if the * operator is overloaded for the QList class, though I don't think it is. Although as mentioned above, you're probably trying to do

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

Depending on what the actual constructor takes.

Also, each of those functions should take in the QList by reference, for performance reasons. Right now you copy the entire object twice for each time you call the function. Once to pass it in by value, then once for the construction of the copy.

One thing to remember when dealing with const'ness is that const is NOT guaranteed. Structures exist such as "const_cast" to strip away the const'ness of an object. Having a const object, and using const functions is helpful to signify to other developers that the code should not change the object, not that it cannot change it. See the difference?

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
}

The useful part is that unintentional attempts to change the object will result in compiler errors, a determined programmer can easily circumvent these protections.

Zeroshade