2009-08-17 75 views
5

我在这里有这段代码。目的是制作initialData的副本。由于我没有以任何方式修改initialData,我认为我应该将它作为const引用传递。但是,我在编译时不断收到此消息。C++和const - 访问const引用的成员函数

的\ src \场面\ SceneAnimationData.cpp(23) :错误C2662: 'SceneTrackerData :: getRect':不能 将 '这个' 从 '常量 SceneTrackerData' 指针 '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); 
} 

回答

13

如果没有SceneTrackerData的定义,这是很难说,但可能是功能(SceneTrackerData::getRect)没有被标记为const。

也就是说,什么是(猜测):

const Rect& SceneTrackerData::getRect(void) 

应该是:

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

一个问题 - 不是const的getRect(void)意味着我不能改变Rect?我知道编译器不能“看到”这个 - 但我的猜测是并非Rect的所有方法都是const。如果没有它们是常量,你不能依赖getRect而不改变Rect。它会更清楚(在这种情况下)抛弃其他功能的常量,而不是在这里添加它? – 2009-08-17 12:30:17

+1

只要getRect不会调用Rect的其他非const方法,或者做任何其他修改,那么getRect可以保证它不会修改Rect。这意味着我可以在const Rect对象上调用getRect - 但是,如果我试图在同一对象上调用另一个非const方法,将会出现编译错误。这就是constness被保留下来的原因:通过让非const方法调用失败,同时允许const方法调用。 – GRB 2009-08-17 16:00:50

1

目前还不清楚这是第23行这里;但是我的猜测是,您正在调用对象上的方法,这些方法本身并未声明为const,因此const对象引用无法使用这些方法。

1

我不确定,因为我不是专家的C++程序员,但是你的函数getRect()等声明为const?如果不是,但你知道你使用它们的方式是const,你仍然可以使用const_cast从initialData引用中删除const。

例如,见这里:http://docs.oracle.com/cd/E19422-01/819-3690/Cast.html

或者斯科特迈尔斯优秀的C++ - 图书Effective C++More Effective C++。至少有一个关于const的项目。

喜欢这些
1

我想行是非法的:

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

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

中,在linkspoints传递不定义为指针,但定义的值。为了编译代码,您可能需要或者定义他们这样

const QList<QGraphicsLineItem*>* links 

,或者改用他们这样

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

然而后者是一个潜在的运行时错误,因为您正在访问临时值的地址,该值在函数体之后死亡。

除非QList使用深度复制,否则您的应用很可能会崩溃。

+0

谢谢。你帮助我追踪了另外2个错误! – Extrakun 2009-08-17 07:23:57

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

这可能是合法的,如果*操作符重载为QList作类,但我不认为它是。虽然如上所述,你可能试图做

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

取决于实际的构造函数。

此外,出于性能方面的原因,这些函数中的每一个都应该引用QList。现在,您每次调用该函数时都会复制整个对象两次。一次通过价值传递,然后一次用于构建副本。

处理常量时要记住的一件事是const不能保证。存在诸如“const_cast”之类的结构去除对象的常量。拥有一个const对象,并使用const函数有助于向其他开发者表​​示代码不应该改变的对象,而不是它不能改变它。看到不同?

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 
} 

的有用的部分是,无意的企图改变对象会导致编译器错误,确定的程序员可以容易地规避这些保护。