调用递归函数时出现编译器错误 - “试图引用已删除的函数”

Posted

技术标签:

【中文标题】调用递归函数时出现编译器错误 - “试图引用已删除的函数”【英文标题】:Compiler error on call to recursive function - "attempting to reference a deleted function" 【发布时间】:2021-12-01 23:11:07 【问题描述】:

我正在尝试使用递归函数将二叉树写入文件。对writeFile(std::string fileName) 的调用打开文件流,然后将其传递给递归函数调用writeFile(BinNode<T> ptr, std::ofstream outFile)。当第一个函数调用第二个函数时,编译器返回错误“尝试引用已删除的函数”(在我的代码中注明的行。我研究了错误代码,我有一个默认构造函数,一个析构函数,所以没有一个函数是隐含的。任何想法将不胜感激。

BinTree.h:

#ifndef BINTREE_H
#define BINTREE_H

#include <iostream>
#include <fstream>
#include "BinNode.h"

template<typename T>
class BinTree 
public:
    BinTree(); // Default constructor
    // Value semantics
    // copy constructor
    BinTree(const BinTree<T>& source);
    // assignment operator
    BinTree<T>& operator=(const BinTree<T>& source);
    // destructor
    ~BinTree()  free(root); 

    bool isEmpty();
    void add(T item);
    void printAll()  print(root); 
    bool readFile(std::string fileName);
    bool writeFile(std::string fileName);

private:
    BinNode<T>* root;
    void free(BinNode<T>* ptr);
    void print(BinNode<T>* ptr);
    void copyTree(BinNode<T>* ptr);
    void writeFile(BinNode<T>* ptr, std::ofstream outFile);
;

#include "BinTree.template"
#endif

BinTree.template:

#include "BinTree.h"
// BinTree.template definition

template <typename T>
BinTree<T>::BinTree() 
    root = nullptr;


template<typename T>
BinTree<T>::BinTree(const BinTree<T>& source) 
    this->root = nullptr;
    copyTree(source->root);


template<typename T>
BinTree<T>& BinTree<T>::operator=(const BinTree<T>& source) 
    if (this == &source)
        return *this;
    free(this->root);
    this->root = nullptr;
    copyTree(source->root);


template<typename T>
bool BinTree<T>::isEmpty() 
    return (root == nullptr);  // true - empty, false - not empty


template<typename T>
void BinTree<T>::add(T item) 
    BinNode<T>* temp = new BinNode<T>(item);  // other constructor

    if (isEmpty())
        root = temp;
    else 
        BinNode<T>* ptr = root;
        while (ptr != nullptr) 
            if (temp->data <= ptr->data)       // Left side
                if (ptr->left == nullptr)      // Left spot open
                    ptr->left = temp;           // Add it
                    ptr = nullptr;              // End Loop
                
                else                           // Left spot not open
                    ptr = ptr->left;
                
            
            else                               // Right side
                if (ptr->right == nullptr)     // Right open
                    ptr->right = temp;          // Add it
                    ptr = nullptr;              // End Loop
                
                else 
                    ptr = ptr->right;
                
            
        
    



template<typename T>
bool BinTree<T>::readFile(std::string fileName) 
    std::ifstream inFS;
    inFS.open(fileName);
    T temp;
    if (!inFS.is_open()) 
        std::cout << "Error opening " << fileName << std::endl;
        return false;
    

    while (!inFS.eof()) 
        getline(inFS, temp);
        add(temp);
    

    inFS.close();

    return true;


template<typename T>
bool BinTree<T>::writeFile(std::string fileName) 
    std::ofstream outFS;
    outFS.open(fileName);
    if (!outFS.is_open()) 
        std::cout << "Error writing to " << fileName << std::endl;
        return false;
    

    writeFile(root, outFS);  // <------ COMPILER ERROR ON THIS LINE ****

    outFS.close();

    return true;


template<typename T>
void BinTree<T>::writeFile(BinNode<T>* ptr, std::ofstream outFile) 
    if (ptr != nullptr) 
        writeFile(ptr->left, outFile);
        outFile << ptr->data << std::endl;
        writeFile(ptr->right, outFile);
    


template<typename T>
void BinTree<T>::free(BinNode<T>* ptr) 
    if (ptr != nullptr) 
        free(ptr->left);
        free(ptr->right);
        delete ptr;
    


template<typename T>
void BinTree<T>::print(BinNode<T>* ptr) 
    if (ptr != nullptr) 
        print(ptr->left);
        std::cout << ptr->data << std::endl;
        print(ptr->right);
    


template<typename T>
void BinTree<T>::copyTree(BinNode<T>* ptr) 
    if (ptr != nullptr) 
        add(ptr->data);
        copyTree(ptr->left);
        copyTree(ptr->right);
    

BinNode.h:

#ifndef BINNODE_H
#define BINNODE_H

template <typename T>
class BinTree;

template <typename T>
class BinNode 
    friend class BinTree<T>;
public:
    BinNode() : left(nullptr), right(nullptr), data(T())  // Default constructor
    BinNode(T item) : left(nullptr), right(nullptr), data(item) 

private:
    BinNode<T>* left;
    BinNode<T>* right;
    T data;

;

#endif

【问题讨论】:

建议:去掉 BinTree.template 中的#include "BinTree.h"。它为您设置了不必要的循环依赖。 当我编译给定的代码时,我得到一个不同的错误:undefined reference to `main' SUGGESTIONS: 1) 查看此线程中的任何回复是否有帮助:***.com/a/37517125/421195 2) 问:究竟是哪一行给出了编译错误? BinTree.h 中的行? 3) 是否有任何理由不能将“BinTree.template”制作为普通的 .cpp 文件,并从 .h 文件中消除 #include “BinTree.template”? "free" 是一个非常不幸的类方法名称,它执行此操作。另外:这个问题显示的代码不符合 *** 显示minimal reproducible example 的要求。因此,这里的任何人都不太可能最终回答这个问题。你需要edit你的问题来展示一个最小的例子,不超过一两页代码(“最小”部分),其他人都可以剪切/粘贴完全如图所示,编译、运行和重现所描述的问题(“可重现”部分,这包括任何辅助信息,如程序的任何输入)。 std::ofstream 不可复制。参考 - void writeFile(BinNode&lt;T&gt;* ptr, std::ofstream&amp; outFile);. 【参考方案1】:

您的函数按值获取std::ofstream,但复制构造函数是deleted: 您需要通过引用传递流:

template<typename T>
void BinTree<T>::writeFile(BinNode<T>* ptr, std::ofstream &outFile) 
    // ...

【讨论】:

以上是关于调用递归函数时出现编译器错误 - “试图引用已删除的函数”的主要内容,如果未能解决你的问题,请参考以下文章

Visual Studio 2013 和 2015 中的 C++ 编译器错误 C2280“试图引用已删除的函数”

VS2019 C++ 错误 C2280 试图引用已删除的函数 inl

在析构函数中调用“delete”运算符时出现编译器错误“编译器堆空间不足”

unique_ptr, qvector.resize() 抛出错误 2280 试图引用已删除的函数

试图找到已删除的函数

创建函数变体向量时出现“调用没有匹配函数”错误