Функции с указателями - PullRequest
       1

Функции с указателями

0 голосов
/ 01 апреля 2011

Как раз тогда, когда я думал, что у меня есть указатели, похоже, я все еще немного сбит с толку. Я пишу оператор = перегрузка, поэтому я хочу освободить память, а затем назначить новую. Я имею дело с классом Quad Tree, где каждое дерево имеет указатель на корневой узел, а корневой узел имеет 4 указателя на 4 дочерних элемента, и у каждого из них есть 4 дочерних элемента. Таким образом, оператор = должен просто сделать копию корня другого дерева и вернуть его. Итак, после освобождения и тому подобного, я пришел к желанию выделить новую память и назначить. Итак, я делаю:

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

А вот моя подпись узла-копира:

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&)

Как мне это исправить?

Ответы [ 5 ]

2 голосов
/ 01 апреля 2011

Если убрать аргументы nodeCopier, эта часть мне не подходит ..

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

nodeCopier возвращает QNode (что на основании вашего утверждения return неявноcastable from 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.root является QtreeNode**, поскольку вы разыменовали его с помощью *, и это выражение, очевидно, привело к QtreeNode*.Либо это, либо root делает какую-то забавную перегрузку оператора.В любом случае вы передали QTreeNode* в функцию, ожидающую QTreeNode&;Вы должны использовать **source.root или (еще лучше) пересмотреть, если source.root должен быть типа QtreeNode**.(Я предполагаю, что это не так.)

Редактировать: Я согласен с тем, что другие говорят, что идиоматический способ C ++ заключается в создании конструктора копирования.Однако я предполагаю, что мой подход заключается в том, чтобы помочь объяснить, почему он не компилируется.Я думаю, чтобы помочь вам преодолеть концептуальный разрыв, было бы неплохо немного попрактиковаться с большим количеством манипуляций с указателями в стиле C ...

0 голосов
/ 01 апреля 2011

При указании «const» для указателя это может относиться к одной или двум вещам. Указатель может быть постоянным (то есть адрес, который содержит указатель, не может быть изменен), или значение, на которое указывает этот адрес, может быть постоянным, или оба они могут быть постоянными. См. здесь для обсуждения.

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.

0 голосов
/ 01 апреля 2011

Похоже, что проблема автора заключается в реализации копирования (operator =). Я бы посоветовал вам реализовать свой оператор = с точки зрения конструктора копирования, т.е. копирования и обмена. Взгляните на этот пример в SO . Посмотрите, как там реализован operator =.

Это в значительной степени даст вам оператор = бесплатно, если вы уже реализовали свой конструктор копирования, поэтому вам не нужно реализовывать этот "nodeCopier" только для назначения копирования.

0 голосов
/ 01 апреля 2011

Вы упомянули оператор = перегрузка в классе, который содержит указатели. Итак, давайте поднимемся на один уровень и посмотрим, что это такое: я подозреваю, что что вам действительно нужно, это конструктор копирования (сначала), а затем использовать поменять идиомы. Что-то вроде:

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 голосов
/ 01 апреля 2011

вам не нужно возвращать 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
}

Надеюсь, это поможет,

Eamonn

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...