C++ ERROR: C2280- compiler error that references deleted function?

C++ ERROR: C2280- compiler error that references deleted function?

我是 C++ 的新手,正在尝试创建一个遵循数学约定(BODMAS 或 PEMDAS)的简单计算器。我做了一个函数计算器,但后来决定更进一步接受变量,此时我一直收到 C2280 错误。

错误是:

token_stream::token_stream(void): attempting to reference a deleted function

我根本不明白这意味着什么,也不知道如何解决它。

这里是 token_stream class:

 class token_stream { //creates a stream of tokens 
 public:
    Token get(); //call to get token function 
    void putback(Token t); //call to token putback function
    void ignore(char a); // call to ignore bad tokens function

private:
    bool full{ false }; //is there a token in the buffer?
    Token buffer; //this is where putback token is stored
};   

这里是完整的计算器代码:

#include "../../std_lib_facilities.h"

//---------------------------------------------------------------------------------------------------

class Token //user defined type with two member functions
{
public:
    char kind;
    double value;
    string name;

    Token(char ch) : kind{ ch } {} //initialize kind with ch
    Token(char ch, double val) : kind{ ch }, value{ val } {} //initialize kind and value
    Token(char ch, string name) : kind{ ch }, name{ name } {} //initialize kind and name 
};
class token_stream { //creates a stream of tokens 
public:
    Token get(); //call to get token function 
    void putback(Token t); //call to token putback function
    void ignore(char a); // call to ignore bad tokens function

    private:
    bool full{ false }; //is there a token in the buffer?
    Token buffer; //this is where putback token is stored
};
class Variable {
public: 
    string name;
    double val;
};

//---------------------------------------------------------------------------------------------------

const char number = '8'; //t.kind==number means that t is a number token
const char quit = 'q'; //t.kind==quit means that t is a quit token
const char print = ';'; //t.kind==print means that t is a print token
const char name = 'a';
const char let = 'L';
const string declr_key = "let";
vector<Variable> var_table;
token_stream ts;
//---------------------------------------------------------------------------------------------------

void token_stream::putback(Token t) {
    if (full) error("putback() is full"); //tests precondition to see if buffer is full
    buffer = t;
    full = true;
}
void token_stream::ignore(char c) {
    if (full && c == buffer.kind) {
        full = false;
        return;
    }
    char ch{ 0 };
    while (cin >> ch) {
        if (c == ch)
            return;
    }
}
Token token_stream::get() { //creates a token from inputs
    if (full) { //checks if we have a token ready
        full = false;
        return buffer;
    }
    char ch;
    cin >> ch;
    switch (ch) {
    case print: 
    case quit: 
    case '(': 
    case ')': 
    case '+':
    case '-': 
    case '*': 
    case '/':
    case '%':
        return Token{ ch }; break; //let each character represent itself
    case '.':                       // floatng point literal can start with a dot
    case '0': case '1': case '2': case '3': case '4':
    case '5': case '6': case '7': case '8': case '9':
    {
        cin.putback(ch);            //putback the digit into input stream
        double val;
        cin >> val;                 //read a floating point number
        Token t{ number,val };
        return t;
        break;
    }
    default:
        if (isalpha(ch)) {
            string s;
            s += ch;
            while (cin.get(ch) && (isalpha(ch) || isdigit(ch))) s += ch;
            cin.putback(ch);
            if (s == declr_key) return Token{ let };
            return Token{ name, s };

        }
        error("Error in Input: Token Invalid"); break;
    }
}

double get_value(string s) {            //gets the value for a given variable
    for (int i = 0; i < var_table.size(); i++)
        if (s == var_table[i].name) return var_table[i].val;
    error("Undefined variable: ", s);
}
void set_value(string s,double d) {     // sets the value for a pre-defined variable 
    for (int i = 0; i < var_table.size(); i++)
        if (s == var_table[i].name) {
            var_table[i].val = d;
            return;
        }
    error("Undefined variable: ", s);
}

//---------------------------------------------------------------------------------------------------

double primary(); //declaration so that term can call primary()
double term() { //does multiplication, division, and modulo
    double left = primary();
    Token t = ts.get();
    while (true)
    {
        switch (t.kind) {
        case '*':
        {
            left *= primary();
            t = ts.get();
            break;
        }

        case '/': {
            double d = primary();
            if (d == 0) error("Divide by 0!"); //non-zero denom check
            else {
                left /= d;
                t = ts.get();
            }
            break;
        }
        case '%': {
            double d = primary();
            if (d == 0)error("Divide by 0!"); //non-zero denom check
            else {
                left = fmod(left, d);
                t = ts.get();
            }
            break;
        }

        default: ts.putback(t); //put back in token strem if none of the other options
            return left; break;
        }
    }
}
double expression() { //handles +, -
    double left = term();
    Token t = ts.get();
    while (true) {
        switch (t.kind) {
        case '+':
        {
            left += term();
            t = ts.get();
            break; }
        case '-': {
            left -= term();
            t = ts.get();
            break; }
        default: ts.putback(t); //put back into token stream if none of the options above
            return left;
            break;
        }
    }

}
double primary() {
    Token t = ts.get();
    switch (t.kind) {
    case '(':
    {
        double d = expression();
        t = ts.get();
        if (t.kind != ')') error("Expected a ')'");
        return d;
        break;
    }
    case number:
        return t.value;
        break;
    case '-': //handles negative numbers
        return - primary();
        break;
    case '+': //handles positive numbers which are preceded by '+'
        return primary();
        break;
    default: error("primary expected: no value after operator given. check input");
    }
}

void check_var(string name) {
    for (int i = 0; i < var_table.size(); i++)
        if (name == var_table[i].name)
            error("Variable name already exists");
}
double define_name(string name, double num) {
    check_var(name);
    var_table.push_back(Variable{ name, num });
    return num;
}
double declaration() {
    // assume we have seen a 'let'
    // handles: name=expression
    // declare a variable called 'name' with value 'val'
    Token t = ts.get();
    if (t.kind != name) error("Expected a variable name"); //throws an error if no variable name given
    string var_name = t.name;

    t = ts.get();
    if (t.kind != '=')error("No '=' sign present in declaration of ", var_name);

    double d = expression();
    define_name(var_name, d);
    return d;
}
double statement() {
    Token t = ts.get();
    switch (t.kind) {
    case let:
        return declaration();
    default:
        ts.putback(t);
        return expression();
    }
}

void clean_up_mess() {
    ts.ignore(print);
}
void calculate() { //expression evaluation loop
    while (cin)
    {
        try {
            Token t = ts.get();
            if (t.kind == print) t = ts.get(); //first discard all 'prints'
            if (t.kind == quit) {
                return;
            }
            ts.putback(t);
            cout << "Answer: " << statement() << "\n";
        }
        catch (exception&e) {
            cout << "Error: " << e.what() << "\n";
            clean_up_mess();
        }
    }
}

//---------------------------------------------------------------------------------------------------

int main()
{
    try {
        cout << "Enter an expression to solve: \n"; //user prompt
        calculate();
        keep_window_open();
    }
    catch(...) {
        cout << "Error of Unknown origin.\n";
    }

}

非常感谢任何帮助!

由于Token没有默认构造函数(可以不带任何参数调用的构造函数),而token_stream包含Token,编译器无法生成默认构造函数token_stream.

两种可能的解决方案:

  1. 将默认构造函数添加到 Token
  2. token_stream 添加一个默认构造函数,它将 buffer 初始化为某个值