2011-04-01 60 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调用的实际参数来解决问题。