First, I am a beginner in C++. Second, I'm sorry of this post turns out to be too long. I have a few classes that make use of each other, similar to this picture (a quick sketch):
And this is a quick sketch of a usable code. The formulas are bogus, but the functionality is close to the real problem. I omitted making source files for simplicity. The #includes
are as they were after the last compile that got me the fewest errors...
"y.h"
#pragma once
#include "a.h"
#include "b.h"
class X;
class A;
class B;
class Y
{
private:
double m_y;
public:
Y(double b, double c):
{
if (c)
m_y = b*b;
else
m_y = sqrt(b);
if (b<0)
{
A::setP(m_y);
A::setQ(m_y + 1);
A::setR(m_y - 1);
}
else
{
B::setP(m_y);
B::setQ(m_y + 1);
B::setR(m_y - 1);
}
}
"a.h"
#pragma once
#include "x.h"
class X;
class A : virtual public X
{
private:
double m_p, m_q, m_r;
public:
A(double a, double b): m_p {a*a}
{
m_q = m_p + 0.5 * b;
m_r = m_q - m_p;
}
void setP(double p) { m_p = p; }
void setQ(double q) { m_q = q; }
void setR(double r) { m_r = r; }
double getP() { return m_p; }
double getQ() { return m_q; }
double getR() { return m_r; }
};
"b.h"
#pragma once
#include "x.h"
class X;
class B : virtual public X
{
private:
double m_p, m_q, m_r;
public:
B(double a, double b): m_p {a + a}
{
m_q = m_p*m_p;
m_r = b + m_q;
}
void setP(double p) { m_p = p; }
void setQ(double q) { m_q = q; }
void setR(double r) { m_r = r; }
double getP() { return m_p; }
double getQ() { return m_q; }
double getR() { return m_r; }
};
"x.h"
//#include "a.h"
class A;
class B;
class X
{
private:
double m_x1, m_x2;
public:
X(double a, double b, double c, int d): m_x1 {2*a}
{
double p, q, r;
switch (d)
{
case 1:
p = A::getP();
q = A::getQ();
r = A::getR();
m_x2 = p * b + q * c - r;
break;
case 2:
p = B::getP();
q = B::getQ();
r = B::getR();
m_x2 = (p - q) * b + r / c;
break;
}
}
double getX1() { return m_x1; }
double getX2() { return m_x2; }
};
"main.cpp"
#include "x.h"
#include <iostream>
int main()
{
X test {3.14, 0.618, 1.618, 1};
std::cout << test.getX1() << '\t' << test.getX2() << '\n';
return 0;
}
My problem is with the necessary includes (assume each class has a header and source file). For now, let's consider only class A in there. main.cpp
only has #include x.h
. To avoid repeating the code with all combinations, I'll try ennumerating what I did, so far:
#include a.h
in class X, then#include y.h
in class A, class Y has no#include
, no forward declarations. The compiler complains aboutexpected class name before {
in both Y and A.add forward declarations to the above =>
invalid use of incomplete type "class ..."
in both Y and A.do it backwards with
#include a.h
in class Y, then#include x.h
in class A, class X has no#include
, with forward declarations =>incomplete type A used in nested name spacifier
in class X, pointing atX(): { int x {A::funcA()} }
.as above and no forward declarations means errors everywhere.
Searches on the net said this happens because of cyclic dependencies, but how can that be since I am only including the previous or the next, never both? There were answers saying that using #pragma once
instead of the usual may resolve the problems, I tried, it's the same incomplete type...
. For reference only, I also tried looking at a few source codes (wxMaxima, audacious) to see how they did it, and it seems they used my first approach.
At this point, I am very confused. If the above can be used for an answer, can someone please give me some directions on how to properly use the #includes
here? If not, please leave a comment and I'll delete this, if needed.