وضع C++ لمشكلة "const".
-
21-12-2019 - |
سؤال
في البداية أود أن أشكر مقدما كل من يجيب على هذا السؤال.مساعدتكم هو موضع تقدير كبير.هذه هي المرة الأولى التي أنشر فيها هنا، لذا أرجو أن تسامحوني إذا نشرت بطريقة سيئة.
سؤالي يتعلق بالنموذج الأولي للطريقة:
void copySubtree(Node<T> * & target, Node<T> * const & original);
وعندما أتصل copySubtree()
في وقت لاحق combineTrees()
.نظرًا لأن الكود موجود حاليًا، فإنه يتم إنشاؤه.لكن ما كان لدي في الأصل هو:
void copySubtree(Node<T> * & target, const Node<T> * & original);
الذي أعطاني الخطأ:
error C2664: 'RootedBinaryTree<T>::copySubtree' : cannot convert parameter 2 from 'RootedBinaryTree<T>::Node<T> *const ' to 'const RootedBinaryTree<T>::Node<T> *&'
وأنا أعلم أنه عندما وضعت const
قبل نوع البيانات في المعلمة، يمنعك من تعديل المعلمة المذكورة في طريقتك، لكنني لا أعرف ماذا تفعل عندما تضعها بعد نوع البيانات، ولست متأكدًا من بناء الكود الخاص بي مع موضع const
بعد أن لم يكن نوع البيانات مجرد صدفة.ماذا يفعل وضع const
بعد نوع البيانات تفعل؟هل سيواجه الكود الخاص بي مشاكل رهيبة في وقت التشغيل بالطريقة المكتوبة حاليًا؟
[أيضًا:أنا بصدد محاولة كتابة تعريفات أسلوب فئة قالب الشجرة الثنائية المتجذرة (وهذا هو السبب في أن بعض الطرق فارغة، وهناك بعض الملاحظات العشوائية لنفسي في التعليقات).لذا أعتذر عن أي إزعاج سببه ذلك.]
إليك الكود ذو الصلة:
RootedBinaryTree.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
RootedBinaryTree.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
شكرًا لك مرة أخرى!
المحلول
القاعدة هي ذلك const
تعلق بالشيء الذي عن يساره، فإذا لم يكن هناك شيء عن اليسار، تعلق بالشيء الذي عن يمينه.إذن في هذه الحالة لدينا:
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
معظم الناس يكتبون const Type
, ، لأن هذه هي الطريقة التي نميل إلى التفكير بها، لكن بعض الناس يفضلون الكتابة Type const
بسبب هذه القاعدة.