【问题标题】:How to correctly use a nested class of a template class?如何正确使用模板类的嵌套类?
【发布时间】:2015-02-13 09:50:20
【问题描述】:

全部! 我正在尝试实现一个简单的模板类二叉搜索树。 我在函数定义方面遇到了几个问题。 以下是我的 BST 类代码

#ifndef BINARY_SEARCH_TREE_H
#define BINARY_SEARCH_TREE_H

#include <iostream>
#include <stdlib.h>

using namespace std;

template<class T>
class BST
{
    struct TreeNode {
        TreeNode* left;
        TreeNode* right;
        T value;
    };

    //member functions
    void destroyTree(TreeNode* leaf);
    void insert(T key, TreeNode* leaf);
    TreeNode* search(T key, TreeNode* leaf);
    void printInOrder(TreeNode* leaf);
    void printPreOrder(TreeNode* leaf);
    void printPostOrder(TreeNode* leaf);

    //memebr variables
    TreeNode* root;
public:

    enum Traversal { INORDER, PREORDER, POSTORDER };

    BST();
    BST(T key);
    ~BST();

    void insert(T key);
    TreeNode* search(T key);
    void printTree(T option);
    void destroyTree();
};

template <class T>
BST<T>::BST()
{
    root = NULL;
};

template <class T>
BST<T>::BST(T key)
{
    root = new TreeNode;
    root->left = NULL;
    root->right = NULL;
    root->value = key;
};

template <class T>
BST<T>::~BST()
{
    destroyTree();
};

template <class T>
void BST<T>::destroyTree(TreeNode* leaf)
{
    if (leaf->left != NULL) destroyTree(leaf->left);
    if (leaf->right != NULL) destroyTree(leaf->right);
    delete leaf;
    leaf = nullptr;
};

template <class T>
void insert(T key, BST<T>::TreeNode* leaf)
{
    if (leaf->value == key)
    {
        cout << "failed inserting node: duplicate item" << endl;
        return;
    }
    else if (leaf->value < key)
    {
        if (leaf->right != NULL) insert(key, leaf->right);
        else
        {
            TreeNode newNode = new TreeNode;
            newNode->left = NULL;
            newNode->right = NULL;
            newNode->value = key;
            leaf->right = newNode;
        }
    }
    else
    {
        if (leaf->left != NULL) insert(key, leaf->left);
        else
        {
            TreeNode newNode = new TreeNode;
            newNode->left = NULL;
            newNode->right = NULL;
            newNode->value = key;
            leaf->left = newNode;
        }
    }
};

template <class T>
BST<T>::TreeNode* BST<T>::search(T key, TreeNode* leaf)
{
    if (leaf == NULL) return NULL;
    if (leaf->value == key) return leaf;
    else if (leaf->vluae < key) return search(key, leaf->right);
    else return search(key, leaf->left);
};

template <class T>
void printInOrder(TreeNode* leaf)
{
    if (leaf->left != NULL) printInOrder(leaf->left);
    cout << leaf->value << " ";
    if (leaf->right != NULL) printInOrder(leaf->right);
};

template <class T>
void printPreOrder(TreeNode* leaf)
{
    cout << leaf->value << " ";
    if (leaf->left != NULL) printPreOrder(leaf->left);
    if (leaf->right != NULL) printPreOrder(leaf->right);
};

template <class T>
void printPostOrder(TreeNode* leaf)
{
    if (leaf->left != NULL) printPostOrder(leaf->left);
    if (leaf->right != NULL) printPostOrder(leaf->right);
    cout << leaf->value << " ";
};

template <class T>
void BST<T>::insert(int key)
{
    if (this->root == NULL)
    {
        this->root = new TreeNode;
        this->root->left = NULL;
        this->root->right = NULL;
        this->root->value = key;
    }
    else insert(key, root);
};

template <class T>
BST<T>::TreeNode* BST<T>::search(int key)
{
    search(key, this->root);
};

template <class T>
void BST<T>::printTree(int option)
{
    switch (option)
    {
    case BST<T>::INORDER:
        printInOrder(this->root);
        cout << endl;
        break;
    case BST<T>::POSTORDER:
        printPostOrder(this->root);
        cout << endl;
        break;
    case BST<T>::PREORDER:
        printPreOrder(this->root);
        cout << endl;
        break;
    }
};

template <class T>
void BST<T>::destroyTree()
{
    destroyTree(this->root);
};

#endif

如您所见,对于void insert(T key, BST&lt;T&gt;::TreeNode* leaf)BST&lt;T&gt;::TreeNode* BST&lt;T&gt;::search(T key, TreeNode* leaf) 函数,我需要对TreeNode 类执行操作,例如返回它的对象或将其传递给函数,这是在@ 类中定义的嵌套类型987654325@。 我得到的错误是语法错误,但我不知道我在代码中做错了什么。 任何意见或建议将不胜感激!

【问题讨论】:

  • 一大堆失踪的BST&lt;T&gt;::s,首先。 search 函数前面还需要一个typename
  • “我得到的错误是语法错误,但我不知道我在代码中做错了什么。”错误肯定包含此信息。但是为了让我们能够使用此信息,您需要发布错误。
  • 插入函数的语法错误是syntax error: identifier 'TreeNode'

标签: c++ nested template-classes


【解决方案1】:

你应该:

  • 将每个TreeNode 替换为BST&lt;T&gt;::TreeNode,因为TreeNode 的定义可能不同,因此编译器需要知道您正在谈论的那个。

  • 在每个BST&lt;T&gt;::TreeNode 前面添加typenameBST&lt;T&gt;::TreeNode 可能有几种不同的定义,甚至有些不是类型,所以你需要告诉编译器它是一个类型。

【讨论】:

  • typename 需要限定名称。
  • 哦,是的,我的错,BST&lt;T&gt; 是必需的限定名称。对不起,错误:)
  • 感谢您的回答!您能否详细说明 typename 关键字?我有点困惑,什么时候需要使用它。此外,在修复语法错误后,我收到了很多我无法阅读的链接错误......它们类似于error LNK2019: unresolved external symbol "private: void __thiscall BST&lt;int&gt;::printPreOrder(struct BST&lt;int&gt;::TreeNode *)" (?printPreOrder@?$BST@H@@AAEXPAUTreeNode@1@@Z) referenced in function "public: void __thiscall BST&lt;int&gt;::printTree(int)" (?printTree@?$BST@H@@QAEXH@Z)
  • 当您在模板中有嵌套符号(如TreeNode)时,编译器几乎不可能确定符号的性质:想想嵌套变量的定义,称为TreeNode!由于模板定义对模板参数很敏感,因此无法确定符号的真实性质。因此,如果您将其用作类型,则应如此声明。这基本上是typename 的目的(即“下一个词是一种类型,暂时相信我!”)。
  • 您应该像 BST&lt;T&gt;::printPreOrder 那样限定您的 printPreOrder 定义。如果不是,您正在定义一个名为 printPreOrder 的函数,而不是 BST&lt;T&gt; 类的方法 printPreOrder
【解决方案2】:
#include <iostream>
#include <stdlib.h>

using namespace std;

template<class T>
class BST
{
    struct TreeNode {
        TreeNode* left;
        TreeNode* right;
        T value;
    };

    //member functions
    void destroyTree(TreeNode* leaf);
    void insert(T key, TreeNode* leaf);
    TreeNode* search(T key, TreeNode* leaf);
    void printInOrder(TreeNode* leaf);
    void printPreOrder(TreeNode* leaf);
    void printPostOrder(TreeNode* leaf);

    //memebr variables
    TreeNode* root;
public:

    enum Traversal { INORDER, PREORDER, POSTORDER };
    BST();
    BST(T key);
    ~BST();

    void insert(T key);
    TreeNode* search(T key);
    void printTree(T option);
    void destroyTree();
};

template <class T>
BST<T>::BST()
{
    root = NULL;
};

template <class T>
BST<T>::BST(T key)
{
    root = new TreeNode;
    root->left = NULL;
    root->right = NULL;
    root->value = key;
};

template <class T>
BST<T>::~BST()
{
    destroyTree();
};

template <class T>
void BST<T>::destroyTree(TreeNode* leaf)
{
    if (leaf->left != NULL) destroyTree(leaf->left);
    if (leaf->right != NULL) destroyTree(leaf->right);
    delete leaf;
    leaf = nullptr;
};

template <class T>
void BST<T>::insert(T key, typename BST<T>::TreeNode* leaf)
{
    if (leaf->value == key)
    {
        cout << "failed inserting node: duplicate item" << endl;
        return;
    }
    else if (leaf->value < key)
    {
        if (leaf->right != NULL) insert(key, leaf->right);
        else
        {
            BST<T>::TreeNode* newNode = new TreeNode;
            newNode->left = NULL;
            newNode->right = NULL;
            newNode->value = key;
            leaf->right = newNode;
        }
    }
    else
    {
        if (leaf->left != NULL) insert(key, leaf->left);
        else
        {
            BST<T>::TreeNode* newNode = new TreeNode;
            newNode->left = NULL;
            newNode->right = NULL;
            newNode->value = key;
            leaf->left = newNode;
        }
    }
};

template <class T>
typename BST<T>::TreeNode* BST<T>::search(T key, typename BST<T>::TreeNode* leaf)
{
    if (leaf == NULL) return NULL;
    if (leaf->value == key) return leaf;
    else if (leaf->vluae < key) return search(key, leaf->right);
    else return search(key, leaf->left);
};

template <class T>
void printInOrder(typename BST<T>::TreeNode* leaf)
{
    if (leaf->left != NULL) printInOrder(leaf->left);
    cout << leaf->value << " ";
    if (leaf->right != NULL) printInOrder(leaf->right);
};

template <class T>
void printPreOrder(typename BST<T>::TreeNode* leaf)
{
    cout << leaf->value << " ";
    if (leaf->left != NULL) printPreOrder(leaf->left);
    if (leaf->right != NULL) printPreOrder(leaf->right);
};

template <class T>
void printPostOrder(typename BST<T>::TreeNode* leaf)
{
    if (leaf->left != NULL) printPostOrder(leaf->left);
    if (leaf->right != NULL) printPostOrder(leaf->right);
    cout << leaf->value << " ";
};

template <class T>
void BST<T>::insert(T key)
{
    if (this->root == NULL)
    {
        this->root = new TreeNode;
        this->root->left = NULL;
        this->root->right = NULL;
        this->root->value = key;
    }
    else insert(key, root);
};

template <class T>
typename BST<T>::TreeNode* BST<T>::search(T key)
{
    search(key, this->root);
};

template <class T>
void BST<T>::printTree(T option)
{
    switch (option)
    {
        case BST<T>::INORDER:
            printInOrder(this->root);
            cout << endl;
            break;
        case BST<T>::POSTORDER:
            printPostOrder(this->root);
            cout << endl;
            break;
        case BST<T>::PREORDER:
            printPreOrder(this->root);
            cout << endl;
            break;
    }
};

template <class T>
void BST<T>::destroyTree()
{
    destroyTree(this->root);
};

现在应该可以工作,但充满了小错误,例如: TreeNode newNode = new TreeNode;, template &lt;class T&gt; void insert 而不是 template &lt;class T&gt; void BST&lt;T&gt;::insert

【讨论】:

    猜你喜欢
    • 2018-02-06
    • 1970-01-01
    • 2019-01-04
    • 1970-01-01
    • 1970-01-01
    • 2011-05-04
    • 1970-01-01
    • 2022-08-22
    相关资源
    最近更新 更多