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
.
两种可能的解决方案:
- 将默认构造函数添加到
Token
- 向
token_stream
添加一个默认构造函数,它将 buffer
初始化为某个值
我是 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
.
两种可能的解决方案:
- 将默认构造函数添加到
Token
- 向
token_stream
添加一个默认构造函数,它将buffer
初始化为某个值