计算多项式的系数作为抽象类数
calculate polynomial with coefficients as abstract class Number
我正在努力添加代表适当数学对象的类Natural, Rational, Complex的操作。我需要它来计算x的多项式
所有类继承抽象类Number。把所有系数放在一个数字数组中,我想计算多项式。要做到这一点,我需要乘以2倍的运算(x是2倍)x被转化为有理并相乘。这很好。我的问题是如何添加抽象类型的类数?
我不能使它工作。所有我得到的是在Number::add(Number)中永不结束的递归(它调用自己而不是调用其他类型的Natural, Rational, Complex的方法)。
# include# include# include# include# include# include# include使用命名空间std;
class Natural;class Rational;class Complex;
class Number {
public:
virtual string toString() const = 0;
virtual Number *operator*(const Rational) const = 0;
virtual Number *add(const Natural*) const = 0;
virtual Number *add(const Rational*) const = 0;
virtual Number *add(const Complex*) const = 0;
virtual Number *add(const Number *n) const {
n->add(this);
}
};
class Natural : public Number {
friend class Complex;
int n;
public:
Natural(const Natural &s) {
n = s.n;
}
Natural(int number) : n(number) {}
string toString() const {
stringstream ss;
ss << n;
return ss.str();
}
operator Rational() const;
operator Complex() const;
operator int() const {
return n;
}
Number *operator*(const Rational r) const;
Number *add(const Natural* number) const {
return new Natural(n + number->n);
}
Number *add(const Rational*) const;
Number *add(const Complex*) const;
};
class Rational : public Number {
friend class Natural;
int numerator, denominator;
void divideByGCD() {
int a = numerator, b = denominator;
//cout << a << ' ' << b << ' ';
if(a < b) {
int temp = a;
a = b;
b = temp;
}
while (b > 0) {
int r = a % b;
a = b; b = r;
//cout << r << endl;
}
numerator /= a;
denominator /= a;
//cout << a << endl;
}
public:
Rational() {}
Rational(const Rational &s) {
numerator = s.numerator;
denominator = s.denominator;
}
Rational(int n, int d) {
if(d == 0) throw new runtime_error("denominator equals 0");
if(d < 0) {
numerator = -n;
denominator = -d;
} else {
numerator = n;
denominator = d;
}
divideByGCD();
}
Rational(double d) {
int i = 0, mul = 1;
int r = d-floor(d);;
while(r!=0) {
i++; mul *= 10;
r = 10*r-floor(10*r);
}
numerator = (int)mul*d;
denominator = mul;
divideByGCD();
}
string toString() const {
stringstream ss;
ss << numerator;
if(denominator > 1) ss << '/' << denominator;
return ss.str();
}
operator const Complex() const;
operator const double() const {
return (double)numerator/denominator;
}
Number *operator*(const Rational r) const {
return new Rational(numerator*r.numerator, denominator*r.denominator);
}
Number *add(const Rational* r) const {
return new Rational(numerator*r->denominator+r->numerator*denominator, denominator*r->denominator);
}
Number *add(const Natural*) const;
Number *add(const Complex*) const;
};
class Complex : public Number {
friend class Rational;
double real, imaginary;
static const double radius = 10;
public:
Complex() {}
Complex(const Complex &s) {
real = s.real;
imaginary = s.imaginary;
}
Complex(const double r, const double im) : real(r), imaginary(im) {}
string toString() const {
stringstream ss;
ss << real;
if(imaginary != 0) ss << '+' << imaginary << 'i';
return ss.str();
}
Number *operator*(const Rational r) const;
Number *add(const Complex* c) const {
return new Complex(real + c->real, imaginary + c->imaginary);
}
Number *add(const Natural*) const;
Number *add(const Rational*) const;
};
Natural::operator Rational() const {
return Rational(n,1);
}
Natural::operator Complex() const {
return Complex(n, 0);
}
Rational::operator const Complex() const {
return Complex((double)numerator/denominator, 0);
}
Number *Natural::operator*(const Rational r) const {
return new Rational(n*r.numerator, r.denominator);
}
Number *Complex::operator*(const Rational r) const {
return new Complex(real*(double)r, imaginary*(double)r);
}
Number *Natural::add(const Rational *r) const {
if(r->denominator == 1) return new Natural(n+r->numerator);
else return new Rational(n*r->denominator,r->denominator);
}
Number *Natural::add(const Complex *c) const {
return c->add(this);
}
Number *Rational::add(const Natural *n) const {
return n->add(this);
}
Number *Rational::add(const Complex *c) const {
return new Complex(c->real+(double)*this, c->imaginary);
}
Number *Complex::add(const Natural *number) const {
return new Complex(real+number->n, imaginary);
}
Number *Complex::add(const Rational *r) const {
return r->add(this);
}
Number *poly(double x, Number *a[], unsigned int size) {
if(size == 1) return a[0];
else return a[0]->add((*poly(x, a+1, size-1))*Rational(x));
}
int main() {
cout << (Natural(5)*(Rational)2.0)->toString() << endl;
Number *coefs[] = {new Natural(5), new Natural(6)};
cout << poly(2, coefs, 2) << endl;
}
我应该如何修复Number::add(Number),以便在调用类型为Number的对象上的add时,程序本身可以确定选择哪种虚拟方法add ?
这就是所谓的多分派。这里有一些链接来看看
Multiple_dispatch
最佳多方法实现
我认为问题是:
virtual Number *add(const Number *n) const {
n->add(this);
}
如果您将一个有理数乘以一个存储在Number *中的Natural,它不能多态地将Number *向上转换为一个Natural *。我同意w/g-makulik的观点,在这里引用/值更有意义,因为你会到处泄漏内存。移除对Number + Number的支持。同样,如果我把一个自然数和一个有理数相加,我得到一个数字*,但它是什么类型的数字?我认为建筑需要更多的思考;我可能会完全摆脱基类纯虚方法(除了toString)。例如:
class Number
{
public:
virtual string toString() = 0;
};
class Rational : public Number
{
string toString() {...}
// forget 'add', use operators
Rational operator+(const Rational & _rhs) const {Rational ret; ...; return ret;}
Rational & operator+=(const Rational & _rhs) const {...; return *this;}
...
}
编辑为了快速修复,我认为您只需要摆脱virtual Number *operator*(const Rational) const = 0;
,并将其替换为每个子类(例如Rational * operator*(const Natural) const
)的版本
或者,向Number添加枚举成员变量以跟踪类型:
enum Type { NATURAL, RATIONAL, ...}
Type mType;
或使用RTTI,这样您就可以在Number::add:
中选择性地选择正确的添加方法。Number * add(Number * _rhs)
{
if(_rhs->mType == RATIONAL)
return this->add((Rational *)_rhs);
...
}
看起来有点邋遢,但是可以用
它看起来像访问者模式是我一直在寻找的。我想让函数在同一类中接受和访问。我认为我的错误是给它们起了相同的名字。
- 无法创建抽象类的实例
- 用pybind11包装C++抽象类时出错
- 如何处理从一个对象传递到另一个在C++中具有公共抽象类的对象的消息
- 有没有办法按值将纯抽象类的所有子类传递给 C++ 中的函数?
- 抽象类错误,请参阅声明" "是抽象的
- 将自定义函数传递到基抽象类中以延迟执行
- 将包含抽象类和普通类C++包导出到 Python
- C++:处理抽象类中的错误时出现问题
- C ++如何在原始抽象类中创建一个函数,该函数接受派生类的输入
- 在 C++ 中使用另一个头文件中的抽象类
- ATL::CComContainedObject<contained>: C2259 无法实例化抽象类
- C++:从抽象类重写纯虚拟运算符重载
- 如何创建shared_ptr抽象类的容器
- .h 或.cpp文件中的抽象类或两者兼而有之?
- 从抽象类继承以创建另一个抽象类时,我应该重新声明所有虚函数吗?
- E0322:不允许使用抽象类类型 " " 的对象
- 可视抽象类 c++(错误 LNK 2001:未解析的外部符号)
- 提升 - 类没有名为"序列化"的成员(抽象类)?
- 如何将子类作为函数的参数传递给期望基类,然后将该对象传递到指向这些抽象类对象的指针向量中?
- 计算多项式的系数作为抽象类数