简体   繁体   中英

C++ and const - accessing a member function of a const reference

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);
}

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

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.

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.oracle.com/cd/E19422-01/819-3690/Cast.html

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

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM