C ++ Platzierung von 'const' -Problemen.
-
21-12-2019 - |
Frage
Zunächst möchte ich mich im Voraus bei allen bedanken, die diese Frage beantworten.Ihre Hilfe wird sehr geschätzt.Ich poste hier zum ersten Mal, Also bitte verzeihen Sie mir, wenn ich mit schlechter Etikette poste.
Meine Frage bezieht sich auf den Methodenprototyp:
void copySubtree(Node<T> * & target, Node<T> * const & original);
und wenn ich rufe copySubtree()
später in combineTrees()
.So wie der Code derzeit ist, wird er erstellt.Aber was ich ursprünglich hatte, war:
void copySubtree(Node<T> * & target, const Node<T> * & original);
was mir den Fehler gab:
error C2664: 'RootedBinaryTree<T>::copySubtree' : cannot convert parameter 2 from 'RootedBinaryTree<T>::Node<T> *const ' to 'const RootedBinaryTree<T>::Node<T> *&'
Ich weiß, dass, wenn Sie setzen const
vor dem Datentyp im Parameter werden Sie daran gehindert, diesen Parameter in Ihrer Methode zu ändern, aber ich weiß nicht, was er bewirkt, wenn Sie ihn nach dem Datentyp setzen, und ich bin mir auch nicht sicher, ob mein Code mit der Platzierung von erstellt wird const
nachdem der Datentyp nicht nur ein Zufall war.Was bedeutet Platzierung const
nach einem Datentyp tun?Wird mein Code schreckliche Laufzeitprobleme haben, so wie er derzeit geschrieben ist?
[Auch:Ich versuche gerade, die Methodendefinitionen der gerooteten Binärbaum-Template-Klassen zu schreiben (weshalb einige der Methoden leer sind und es in den Kommentaren einige zufällige Notizen für mich gibt).Ich entschuldige mich für die dadurch verursachten Unannehmlichkeiten.]
Hier ist der relevante Code:
Verwurzelter Binärbaum.h
#ifndef ROOTEDBINARYTREE_H
#define ROOTEDBINARYTREE_H
template <class T>
class RootedBinaryTree
{
private:
template <class T>
struct Node
{
T nodeData;
Node<T> * leftChild;
Node<T> * rightChild;
};
Node<T> * root;
Node<T> * currentPosition;
void copySubtree(Node<T> * & target, Node<T> * const & original);
void deleteSubtree(Node<T> * n);
public:
RootedBinaryTree(const T & rootData);
RootedBinaryTree(const RootedBinaryTree<T> & original);
~RootedBinaryTree();
void toRoot();
bool moveLeft();
bool moveRight();
T getData() const {return currentPosition->nodeData;};
RootedBinaryTree<T> & operator=(const RootedBinaryTree<T> & RHS);
void combineTrees(const RootedBinaryTree<T> & leftTree, const RootedBinaryTree<T> & rightTree);
void setNodeData(const T & nodeData);
};
#endif
Verwurzelter Binärbaum.cpp
#ifndef ROOTEDBINARYTREE_CPP
#define ROOTEDBINARYTREE_CPP
#include "RootedBinaryTree.h"
template<class T>
void RootedBinaryTree<T>::copySubtree(Node<T> * & target, Node<T> * const & original)
{
// later add something here to delete a subtree if the node we are trying to assign to has children
// perhaps a deleteSubtree() method
target = new Node<T>;
if(original->leftChild != 0L)
{
copySubtree(target->leftChild, original->leftChild);
}
else
{
target->leftChild = 0L;
}
// ^^^ copy targets left (and right) children to originals
if(original->rightChild != 0L)
{
copySubtree(target->rightChild, original->rightChild);
}
else
{
target->rightChild = 0L;
}
target->nodeData = original->nodeData;
}
template <class T>
void RootedBinaryTree<T>::deleteSubtree(Node<T> * n) // Done
{// Assumes that n is a valid node.
if(n->leftChild != 0L) deleteSubtree(n->leftChild); // Delete all nodes in left subtree
if(n->rightChild != 0L) deleteSubtree(n->rightChild); // Delete all nodes in right subtree
delete n;
}
template <class T>
RootedBinaryTree<T>::RootedBinaryTree(const T & rootData) // Done
{
root = new Node <T>;
root->leftChild = 0L;
root->rightChild = 0L;
root->nodeData = rootData;
currentPosition = root;
}
template <class T>
RootedBinaryTree<T>::RootedBinaryTree(const RootedBinaryTree<T> & original)
{
}
template <class T>
RootedBinaryTree<T>::~RootedBinaryTree()
{
deleteSubtree(root); // root will be valid because of our constructor and other methods
root = currentPosition = 0L;
}
template <class T>
void RootedBinaryTree<T>::toRoot() // Done
{
currentPosition = root;
}
template <class T>
bool RootedBinaryTree<T>::moveLeft() // Done
{
if(currentPosition->leftChild == 0L) return false;
currentPosition = currentPosition->leftChild;
return true;
}
template <class T>
bool RootedBinaryTree<T>::moveRight() // Done
{
if(currentPosition->rightChild == 0L) return false;
currentPosition = currentPosition->rightChild;
return true;
}
template <class T>
RootedBinaryTree<T> & RootedBinaryTree<T>::operator=(const RootedBinaryTree<T> & RHS)
{
}
template <class T>
void RootedBinaryTree<T>::combineTrees(const RootedBinaryTree<T> & leftTree, const RootedBinaryTree<T> & rightTree)
{ // Copies leftTree into root's left tree and rightTree into root's right tree.
if(root->leftChild != 0L) deleteSubtree(root->leftChild);
if(root->rightChild != 0L) deleteSubtree(root->rightChild);
copySubtree(root->leftChild, leftTree.root);
copySubtree(root->rightChild, rightTree.root);
}
template <class T>
void RootedBinaryTree<T>::setNodeData(const T & nodeData)
{
currentPosition->nodeData = nodeData;
}
#endif
Nochmals vielen Dank!
Lösung
Die Regel ist, dass const
heftet sich an das Ding zu seiner Linken, und wenn links nichts ist, heftet es sich an das Ding zur Rechten.In diesem Fall haben wir also:
const Node *p; // p is a pointer to a const Node
Node const *p; // same again, p is a pointer to a const Node
Node * const p; // p is a const pointer to a (mutable) Node
const Node * const p; // p is a const pointer to a const Node
Node const * const p; // same again, p is a const pointer to a const Node
Die meisten Leute schreiben const Type
, weil wir so über sie denken, aber manche Leute schreiben lieber Type const
wegen dieser Regel.