假设我有一堆像这样的继承类:
......它们都是为了制作各种多项式。类X
主要是变量槽,类A
,B
等都是virtual public X
,每个都创建ont类型的多项式,类Y
进行调用。除了A
和B
之外,还可以添加任何其他类。
现在,一切正常,但是对于新添加的“虚拟公共”类,我需要重用其他类中的一些成员函数,这里来自类A
内的B
。我试着做出最简单的例子:
#include <iostream>
#include <cmath>
#include <functional>
// variable tank
class X
{
protected:
// general variables
double *m_c;
int m_n;
double m_w;
// funcX related
double m_r;
int m_i {0};
public:
~X() = default;
/* Simple bracketed root-finding. This is called from more than
* one "virtual public" classes.
*/
const double funcX(const double &x, const double &y, \
std::function<const double(const double&, const int&)> fp, \
const int &k)
{
double a {x}, b {y}, fmid;
while (m_i<100)
{
m_r = 0.5*(a + b);
fmid = fp(m_r, k);
if (fabs(b-a) <= 1e-3)
break;
if (fmid < 0)
b = m_r;
else
a = m_r;
++m_i;
}
return m_r;
}
};
// one of the many classes that generate polynomials
class A: virtual public X
{
public:
void funcA(const int &n)
{
// set order
m_n = n;
// calculate X::m_c[i]
m_c = new double[m_n+1];
for (short i=0; i<=m_n>>1; ++i)
{
int sgn {i%2 ? -1 : 1};
m_c[i<<1] = sgn/((i + 1.0)*(i + 1.0));
}
// The polynomial is zero somewhere, use funcX() to find where.
m_w = funcX(5.0, 0.0, \
[this](const double &x, const int &n) \
{ return calcA(x, n); }, \
m_n);
}
// calculates the value of the polynomial of order n, at x
const double calcA(const double &x, const int &n) const
{
double out {static_cast<double>(m_c[0])};
for (short i=1; i<=n; ++i)
out = m_c[i] + x*out;
return out;
}
};
class B: virtual public X
{
private:
A m_a; // otherwise the lambda function does not "catch" it
public:
void funcB(const int &n)
{
// same as in A
m_n = n;
// same as in A, calculate coefficients
m_c = new double[m_n+1];
for (short i=0; i<=m_n; ++i)
{
int sgn {i%2 ? -1 : 1};
m_c[i] = sgn/((i + 1)<<1);
}
/* Here I need A::calcA(). Instead of duplicating the code,
* I want to call it through X::funcX(). The code compiles,
* but it crashes.
*/
m_w = funcX(0.5, 1.0, \
[this](const double &x, const int &n) \
{ return m_a.calcA(x, n); }, \
m_n);
}
const double getW() const { return m_w; }
};
class Y: public A, public B
{
public:
Y(const int &n, const int &i)
{
// call one of the "virtual public" classes through i
switch (i)
{
case 1: funcA(n); break;
case 2: funcB(n); break;
}
}
void printC() { for (short i=0; i<=m_n; ++i) std::cout << m_c[i] << '\n'; }
void printW() { std::cout << m_w << '\n'; }
void printA(const double &x, const double &n) { std::cout << A::calcA(x, n) << '\n'; }
};
int main(int argc, char *argv[])
{
int N {6};
Y *y;
for (short i=1; i<=2; ++i)
{
y = new Y(N, i);
y->printC();
y->printW();
y->printA(1.2, N);
}
return 0;
}
班级X
:
X::funcX()
是一种简单的根查找算法,可以在多个virtual public
类(A
,B
等中调用。 m_c
,m_n
,m_w
是共享变量。
课程A
和B
:
他们的主要功能是funcA()
(和funcB()
,依此类推)并根据计算的顺序创建多项式(在体内,有一个for
循环), X::m_n
。评估多项式为A::calcA()
。这需要由class B
调用,或者重新定义。因为代码膨胀,我宁愿避免使用后者。对于我相当初学的水平,它看起来也不是很“专业”...
班级Y
这会根据参数virtual public
(i
)调用任何switch/case
类。
代码编译,但崩溃了。它打印的情况下。此示例指向A::funcA()
作为罪魁祸首,但在原始程序中,我可以看到系数m_c[i]
甚至没有使用动态内存进行初始化,就像尝试打印m_c[0]
一样崩溃。我尝试在new double[]
中移动A
insode函数,但这不起作用。
我不知道如何制作它。这是否有意义,是否可能?如果是,怎么样?
修改:忘记添加我不能只将calcA()
从A
移到X
的顶部,因为每个多项式的评估方式都不同,就像有快捷方式一样,每一个中的变化都可以对每个多项式进行不同的优化评估。我可以使X::calcA()
成为一个通用的,但是会有性能损失,我宁愿不付钱。
答案 0 :(得分:4)
似乎您的问题是由设计问题引起的。当您需要使用其他类中可能意味着的方法时:
让我们更接近你的榜样。您正在使用虚拟多重继承,这被认为是非常繁重的模式,通常不应使用。此外,您的代码中没有虚拟方法,因此您实际上根本不使用继承。您要么必须删除继承,要么考虑对所有类都有意义的常用方法。对于函数,这似乎是在指定点计算函数值的能力。然后移动所有代码,而不是从类中描述多项式或函数。移出数值解算器。这将允许为所有类重用它们,以支持所需的接口。完全摆脱Y课程。看来,需要使用开关和枚举来模拟虚拟方法。你不需要它,如果它们在语义上是相同的,那么将funcA和funcB重命名为func,并为不同类型的多项式做同样的事情。