1

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):

classes

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 about expected 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 at X(): { 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.

a concerned citizen
  • 787
  • 2
  • 9
  • 25
  • Firts, please provide [Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve) of your code. Second, _"class X uses class A "_ is not clear. Does `X` derive from `A` or holds reference to its instance? Third, it is very good that you decided to provide graphical representation of your classes relationship, so you can go further and learn [UML](https://en.wikipedia.org/wiki/Unified_Modeling_Language) a bit – mvidelgauz Aug 14 '16 at 08:15
  • @mvidelgauz Thank you for the notices, I'll try to make a minimal usable code. Will this mean I have to start from scratch with the question? As in, delete, remake? – a concerned citizen Aug 14 '16 at 08:19
  • You should be able to edit your question, don't you have 'edit' link under it? – mvidelgauz Aug 14 '16 at 08:21
  • @mvidelgauz I do, but if I do that, it means changing almost everything. It's very possible that people who already read this won't try to read it again. At any rate, I'm rethinkiing it now, and see where it goes. – a concerned citizen Aug 14 '16 at 08:24
  • 1. People who will start answering will see "question has been edited" message without reloading page - SO is smart enough to maki it ))). 2. Your question is staying in "unanswered" list anyway so making it phrased and formed better will only improve chances of getting good answer(s) – mvidelgauz Aug 14 '16 at 08:33
  • You fundamentally have a cyclic dependency - X is calling methods from A and B, but they derive from X. It's not clear what you're trying to achieve here - what do you expect those calls to do? (They won't compile for other reasons.). And what is the relevance of Y? – Oliver Charlesworth Aug 14 '16 at 09:58
  • @OliverCharlesworth How do they derive from X? Is it because of the same parameters? The usage is: create X object, who calls A or B to calculate `m_p/m_q/m_r`, who may or may not be changed by Y depending n the values of `a/b/c` passed to X. – a concerned citizen Aug 14 '16 at 10:12
  • `class A : public virtual X`... – Oliver Charlesworth Aug 14 '16 at 10:13
  • @OliverCharlesworth I thought that is used to solve the "diamond problem"? To avoid creating X twice (or however many times depending on how many classes, A, B, C, ...)? Don't get me wrong, I'll take any solution there is. (Now I see I forgot to add `public A, public B` to Y class, I'm sorry). – a concerned citizen Aug 14 '16 at 10:20
  • I have to be honest - almost everything about your code is broken (cyclic dependencies, classes that don't get used at all, missing calls to base constructors, unnecessary forward declarations, unnecessary inheritance, trying to call non-static methods in a static way, ...). Thus I'm not quite sure what to suggest at this point, other than taking a step back and re-thinking what you want to achieve. – Oliver Charlesworth Aug 14 '16 at 10:27
  • Have a read around the following pages and see if these help you develop a clearer picture in your mind of what you wish to achieve as suggested by [Oliver](https://stackoverflow.com/users/129570/oliver-charlesworth), and how you might go about it: [Think like a compiler](http://stackoverflow.com/a/628079/5012644), [Include Guards](https://en.wikipedia.org/wiki/Include_guard). – cognophile Aug 14 '16 at 11:02
  • I see I have to better arrange my thoughts in this. Thank you all for the answers. @cognophile The first link does help, indeed. Now, I have to squeeze the neuron. – a concerned citizen Aug 14 '16 at 11:24

0 Answers0