2009-08-17 77 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 
} 

的有用的部分是,無意的企圖改變對象會導致編譯器錯誤,確定的程序員可以容易地規避這些保護。