2011-04-01 83 views
0

就在我以爲我有指針的時候,看起來好像還是有點困惑。我正在寫運算符=重載,所以我想取消分配內存然後分配新的。我正在處理一個四叉樹類,其中每棵樹都有一個指向根節點的指針,而一個根節點有4個指向4個孩子的指針,而每個樹有4個孩子。所以operator =應該只是複製另一個樹的根並返回它。所以在釋放之後,我想要分配新的內存和分配。所以,我做的:帶指針的函數

root=new QtreeNode; 
root=nodeCopier(*(source.root)); 

這是我的nodeCopier簽名:

QNode nodeCopier(const QtreeNode & n) { 
    QtreeNode tempNode; 

    //stuff 

    return tempNode; 
} 

但後來我得到這個錯誤錯誤:

no matching function for call to 
    Qtree::nodeCopier(Qtree::QtreeNode* const&) 
    qtree.h:92: note: candidates are: Qtree::QtreeNode Quadtree::nodeCopier(const Qtree::QtreeNode&) 

我該如何解決這個問題?

+0

你可以發佈你的'QtreeNode'類的聲明嗎? – 2011-04-01 17:28:46

回答

2

拿走的nodeCopier的論點,這部分沒有按看起來不對我..

root=new QtreeNode; 
root=nodeCopier(/* ... */); 

nodeCopier返回QNode(根據您的return聲明可以從QtreeNode隱式轉換),但從第一行我們可以將它分配到QtreeNode*。或者更一般地說,你正在將一個非指針數量指定給一個指針。

它看起來像你可能想做的事:

*root = nodeCopier(/* ... */); 

的第二個問題,我可以根據這裏的第二行和錯誤消息看。

root=nodeCopier(*(source.root)); 

Qtree::nodeCopier(Qtree::QtreeNode* const&) 
qtree.h:92: note: candidates are: 
    Qtree::QtreeNode Quadtree::nodeCopier(const Qtree::QtreeNode&) 

在此基礎上,它看起來像source.rootQtreeNode**,因爲你*取消引用它,這顯然表達產生QtreeNode*。無論是或root做一些非常時髦的運算符重載。無論如何,你通過一個QTreeNode*到一個函數期望QTreeNode&;如果source.root需要QtreeNode**類型,則應使用**source.root或(更好)重新評估。 (我的猜測是沒有。)

編輯:我同意其他人的說法,慣用的C++方法是創建一個拷貝構造函數。不過,我想我的方法是幫助解釋爲什麼它不編譯。我想幫助你彌合概念上的差距,這將是很好的獲得一些練習更多的C型指針操縱...

0

你不需要返回QtreeNode如果你在一個指針傳遞,而不是你應該

root=new QtreeNode();      //declare a new QtreeNode 
root=nodeCopier(&(source.root));   //pass a pointer to root into nodeCopier 

void nodeCopier(const QtreeNode* n) {  
    QtreeNode tempNode = new QtreeNode(); //declare a local QtreeNode 

    //stuff 

    *n = tempNode;       //dereference root pointer and assign tempnode 
    delete(tempNode);      //Delete tempNode to prevent memory Leak 
} 

希望這有助於

埃蒙·

+0

我仍然在這裏得到一個錯誤。 'n'不是一個指針,那麼爲什麼你在最後一行中解除引用呢? – Snowman 2011-04-01 17:31:16

+0

對不起,請參閱我的最新編輯,您需要將*放在函數參數中以傳入指針,並在調用函數時使用&。 *變量聲明之後表示將此變量聲明爲一個指針,*之前變量名錶示取消引用此指針,&表示使用傳遞此變量的內存位置 – 2011-04-01 17:36:48

0

你提到了一個運算符=超載,包含 指針的類。所以讓我們上一層,看看它是什麼:我懷疑 你真正需要的是複製構造函數(第一個),然後使用 交換習慣用法。喜歡的東西:

QtreeNode::QtreeNode(QtreeNode const& other) 
    : north(other.north == NULL ? NULL : new QtreeNode(*other.north)) 
    , east(other.east == NULL ? NULL : new QtreeNode(*other.east)) 
    , south(other.south == NULL ? NULL : new QtreeNode(*other.south)) 
    , west(other.west == NULL ? NULL : new QtreeNode(*other.west)) 
{ 
} 

QtreeNode& QtreeNode::operator=(QtreeNode const& other) 
{ 
    QtreeNode tmp(other); 
    swap(tmp); 
    return *this; 
} 

void QtreeNode::swap(QtreeNode& other) 
{ 
    std::swap(north, other.north); 
    std::swap(east, other.east); 
    std::swap(south, other.south); 
    std::swap(west, other.west); 
} 

什麼,你肯定不希望做的是 之前刪除現有的節點上,您已經成功複製了新樹;這肯定是 未定義的行爲---通常以雙刪除的形式。

而且你不需要複製的特殊功能;上面的複製構造函數 是遞歸的,並且會爲您處理所有事情。

0

看起來像海報的問題是實施複製分配(運算符=)。我建議你根據拷貝構造函數(即拷貝和交換)來實現你的operator =。看看this example in SO。看看operator =是如何實現的。

如果您已經實現了您的拷貝構造函數,那麼這將爲您免費提供operator =運算符,因此您不需要爲了拷貝分配而實現此「nodeCopier」。

0

當在指針上指定「const」時,它可以應用於一兩件事情。指針可以是常數(即指針所包含的地址不能改變),或者該地址指向的值可以是常數,或者它們都可以是常數。有關討論,請參見here

const QtreeNode *  p1 = <value>; // non-constant pointer to  constant value 
     QtreeNode * const p2 = <value>; //  constant pointer to non-constant value 
const QtreeNode * const p3 = <value>; //  constant pointer to  constant value 

如你的問題所示,nodeCopier函數接受一個常量QtreeNode的引用。從錯誤信息,我們可以看到,所述編譯器尋找一個nodeCopier該需要參照本發明的恆定指針QtreeNode

Qtree::nodeCopier(Qtree::QtreeNode* const&) 

換句話說*(source.root)的類型不匹配的類型nodeCopier函數的形式參數。您可以通過更改nodeCopier的定義或更改傳遞給nodeCopier調用的實際參數來解決問題。