是否有可能重载将抽象类的引用/指针作为输入的运算符? 我正在研究一个C++程序,它必须用给定表达式的符号进行微分。例如,(5x)的导数将是((0*x)+(5*1))。请注意,整数系数也被视为变量或函数,因此使用乘积规则。另一个例子:(5+(8*x))将计算为(0+((0*x)+(8*1))。无需进一步简化
该任务要求有一个带有纯虚方法的抽象基类“表达式”,并从中派生出数字、变量等派生类。目标是读取上述形式的表达式并打印出它们各自的符号导数 我在处理这项任务方面取得了一些成功,没有使任何操作员超负荷工作。我的意思是:是否有可能重载将抽象类的引用/指针作为输入的运算符? 我正在研究一个C++程序,它必须用给定表达式的符号进行微分。例如,(5x)的导数将是((0*x)+(5*1))。请注意,整数系数也被视为变量或函数,因此使用乘积规则。另一个例子:(5+(8*x))将计算为(0+((0*x)+(8*1))。无需进一步简化,c++,oop,inheritance,polymorphism,operator-overloading,C++,Oop,Inheritance,Polymorphism,Operator Overloading,该任务要求有一个带有纯虚方法的抽象基类“表达式”,并从中派生出数字、变量等派生类。目标是读取上述形式的表达式并打印出它们各自的符号导数 我在处理这项任务方面取得了一些成功,没有使任何操作员超负荷工作。我的意思是: #include <iostream> #include <string> class Expression { public: virtual Expression* diff() = 0; //Derivative Calculator
#include <iostream>
#include <string>
class Expression
{
public:
virtual Expression* diff() = 0; //Derivative Calculator
virtual void print() = 0;
virtual std::string stringget() = 0; //Prints current expression
};
//--------------------Number Class--------------------//
class Number : public Expression
{
private:
int num;
std::string snum;
public:
//Constuctors
Number(int n) : num(n), snum(std::to_string(num)) { }
Number() : num(0), snum("0") { }
// Rule of three does not apply as class does not contain pointer variables
//Differentiation function
Expression* diff()
{
num = 0;
snum = std::to_string(0);
return this;
}
void print()
{
std::cout << num << std::endl;
}
std::string stringget()
{
return snum;
}
};
//--------------------Variable Class--------------------//
class Variable : public Expression
{
private:
std::string var;
public:
//Constructors
Variable(std::string v) : var(v) { }
Variable() : var("x") { }
//Functions
Expression* diff() override
{
var = "1";
return this;
}
void print() override
{
std::cout << var << std::endl;
}
std::string stringget() override
{
return var;
}
};
//--------------------Addition/Sum Class--------------------//
class Add : public Expression
{
private:
std::string sum;
std::string plus = "+";
std::string leftpar = "(";
std::string rightpar = ")";
Expression* laddend; //left addend storage
Expression* raddend; //right addend storage
public:
//Constructors
Add(Expression* a, Expression* b)
{
sum = leftpar + (*a).stringget() + plus + (*b).stringget() + rightpar;
laddend = a;
raddend = b;
}
Add(Expression& a, Expression& b)
{
sum = leftpar + (a).stringget() + plus + (b).stringget() + rightpar;
laddend = &a;
raddend = &b;
}
//Copy Constructor
Add(const Add& src) : sum(src.sum), plus(src.plus), leftpar(src.leftpar), rightpar(src.rightpar), laddend(src.laddend), raddend(src.raddend) { }
//Assignment operator
Add& operator =( Add& src ) { sum = src.sum; return *this; }
//Destructor
~Add() { delete laddend; delete raddend; laddend = NULL; raddend = NULL;}
//
void print() override
{
std::cout << sum << std::endl;
}
//derivative calculator
Expression* diff() override
{
laddend = (*laddend).diff();
raddend = (*raddend).diff();
sum = leftpar + (*laddend).stringget() + plus + (*raddend).stringget() + rightpar;
return this;
}
//Expression getter
std::string stringget() override
{
return sum;
}
//Overload
Expression& operator +( Expression* rhs)
{
Add* res = new Add(this, rhs);
return *res;
}
};
//--------------------Product/Multiplication Class--------------------//
class Mul : public Expression
{
private:
std::string product = "(";
std::string ast = "*";
std::string plus = "+";
std::string leftpar = "(";
std::string rightpar = ")";
Expression* multiplicand; //left argument storage
Expression* multiplier; //right argument storage
public:
//Constructors
Mul(Expression* a, Expression* b)
{
product = product + (*a).stringget() + ast + (*b).stringget() + rightpar;
multiplicand = a;
multiplier = b;
}
void print() override
{
std::cout << product << std::endl;
}
Expression* diff() override
{
std::string lvar = (*multiplicand).stringget(); //before differentiation
std::string rvar = (*multiplier).stringget(); //before differentiation
multiplicand = (*multiplicand).diff();
multiplier = (*multiplier).diff();
product = leftpar + leftpar + (*multiplicand).stringget() + ast + rvar + rightpar + plus + leftpar + lvar + ast + (*multiplier).stringget() + rightpar + rightpar;
return this;
}
std::string stringget() override
{
return product;
}
//Overload
Expression& operator *( Expression* rhs)
{
Mul* res = new Mul(this, rhs);
return *res;
}
};
int main()
{
Expression* test = new Mul(new Number(6), new Variable("x"));
std::cout << "Current Expression: " << test->stringget() << std::endl;
Expression* test2 = test->diff();
std::cout << "Differentiated Expression: " << test2->stringget() << std::endl;
Add x(test, test2);
// x = test + test2 * test;
delete test;
return 0;
}
现在,表达式(6*x)
是通过行创建的
Expression*test=new Mul(新数字(6),新变量(“x”)代码>
但是,由于我的目标是读取形式为(6*x)
的表达式以及更复杂的表达式,例如((4*x)+(x*x))-x)
,然后解释它们并最终进行区分,因此唯一的方法是重载运算符。这就是我遇到问题的地方
问题
正如您可能在代码中注意到的,我重载了加法和乘法运算符。但是,当我尝试运行以下代码时
x=test+test2*test1代码>
(这一行在上面提供的代码中被注释掉)我得到一个错误。此外,例如,即使只有一个操作员
test=test+test2代码>
我得到了错误
must have an argument of class or enumerated type
错误:“Expression*”和“Expression*”类型的操作数对二进制“operator+”无效。
或
错误:“Expression*”和“Expression*”类型的操作数对二进制“operator+”无效。
这对我来说没有意义,因为参数类型是一致的
我还试过什么?
我试图通过引用和常量引用传递参数,但结果仍然相同。我还尝试将运算符重载描述作为非成员函数编写,但这会导致错误
must have an argument of class or enumerated type
我还尝试将返回类型从Expression&
更改为Expression*
,并进行必要的后续编辑,但错误相同。我甚至尝试为所有类实现三的规则——尽管这不是必需的——但结果是一样的
如果你能帮我找到我错过的地方,我将不胜感激 你的代码太多了。你应该把它减少,直到你得到一个仍然重现错误的答案。我按照指南做了,把它减少到主要部分。问题是,大部分都是相互依赖的。@E.Nole:我们不需要看到微分部分,只需要一个带运算符的类就行了。指针不是引用。不能重载指针的运算符。指针在类型中拼写为*
。引用在类型中用&
拼写。指针和引用不可互换。如果函数通过引用接受参数,则不要传递指针(反之亦然)。您经常遇到的问题是,您混合使用指针和引用,好像它们是可互换的。最好从头开始重新设计类,并正确使用引用。在C++中使用<代码>新< /COD>创建值是错误的(实际上,您使用的是java技术,但是C++中的工作方式不同,因此您的问题)。代码太多。你应该把它减少,直到你得到一个仍然重现错误的答案。我按照指南做了,把它减少到主要部分。问题是,大部分都是相互依赖的。@E.Nole:我们不需要看到微分部分,只需要一个带运算符的类就行了。指针不是引用。不能重载指针的运算符。指针在类型中拼写为*
。引用在类型中用&
拼写。指针和引用不可互换。如果函数通过引用接受参数,则不要传递指针(反之亦然)。您经常遇到的问题是,您混合使用指针和引用,好像它们是可互换的。最好从头开始重新设计类,并正确使用引用。在C++中使用<代码>新< /COD>创建值是错误的(实际上,您使用的是java技术,但是C++中的工作方式不同,因此您的问题)。