0

I was trying to write some code with classes instead of structures (Some task that our proffesor gave us), The task is to convert from Cartesian to Spherical and the other way around, so dont bother with some finesses (namespace, encapsulation...) that is not accented in this very example. I encountered a very silly error that i haven't seen so far, and i am unfortunately unable to solve it..

If you pay attention you will see that there are two methods with identical names (ToMe(...)) and even parameters (The only difference is the parameter type). When i run this code with declaration of the ToMe procedure in Decard Class commented i get the desired result, but when i want to run it in this shape it says the following:

error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
error C2143: syntax error: missing ',' before '&'
error C2065: 'S': undeclared identifier

Does anyone have any clue to why it keeps breaking?

#include<iostream>
#include<math.h>
using namespace std;

class Decard
{
    double m_x;
    double m_y;
    double m_z;
public:
    Decard() :m_x{0}, m_y{ 0 }, m_z{ 0 } {}
    Decard(double x, double y, double z) :m_x{ x }, m_y{ y }, m_z{ z }{}
    double GetX() const { return m_x; }
    double GetY() const { return m_y; }
    double GetZ() const { return m_z; }
    void Ucitaj()
    {
        cout << "Unesite koordinate tacaka u dekartovom koordinatnom sistemu x,y, i z respektivno" << endl;
        cin >> m_x >> m_y >> m_z;
    }
    void ToMe(const Spheric& S) //THIS IS THE LINE THAT MAKES PROBLEMS
    {
        m_x = S.GetR() * sin(S.GetTheta()) * cos(S.GetPhi());
        m_y = S.GetR() * sin(S.GetTheta()) * sin(S.GetPhi());
        m_z= m_x = S.GetR() * cos(S.GetTheta());
    }
    void Print()
    {
        cout << "U dekartovom :" << endl;
        cout << "X:" << m_x << endl << "Y:" << m_y << endl << "Z:" << m_z << endl;
    }
};
class Spheric
{
    double m_r;
    double m_phi;
    double m_theta;
public:
    Spheric() :m_r{ 0 }, m_phi{ 0 }, m_theta{ 0 } {}
    Spheric(double x, double y, double z) :m_r{ x }, m_phi{ y }, m_theta{ z }{}
    void Ucitaj()
    {
        cout << "Unesite koordinate tacaka u sfernom koordinatnom sistemu r,fi, i teta respektivno" << endl;
        cin >> m_r >> m_phi >> m_theta;
    }
    void Print()
    {
        cout << "U sfernom :" << endl;
        cout << "R:" << m_r << endl << "Phi:" << m_phi << endl << "Theta:" << m_theta<< endl;
    }
    void ToMe(const Decard& D)
    {
        m_r = sqrt(pow(D.GetX(), 2) + pow(D.GetY(), 2) + pow(D.GetZ(), 2));
        m_phi = atan(D.GetY() / D.GetX());
        m_theta = atan(D.GetZ() / m_r);
    }
    double GetR() const { return m_r; }
    double GetPhi() const { return m_phi; }
    double GetTheta() const { return m_theta; }

};

int main()
{
    Decard D{ 1,2,3 };
    Spheric S;
    S.ToMe(D);
    S.Print();
    D.ToMe(S);
    D.Print();
    return 0;
}

What i have tried is placing the definition of the procedure outside of the class:

void Decard::ToMe(const Spheric& S)
{
.
.
.
}

And i saw something interesting, Visual Studio pointed out that the parameter type of this outplaced defenition does not match "const <error_type> &S" in the declaration of the procedure.

tadman
  • 208,517
  • 23
  • 234
  • 262
Meda
  • 21
  • 6
  • 2
    You need to forward declare `Spheric` or move that above the other. Remember the compiler reads top down, it does not skip ahead. – tadman Jan 15 '23 at 20:38
  • I suspected that the problem is both of these classes depend on each other :/ – Meda Jan 15 '23 at 20:41
  • Read the first part of my comment again, then. That's usually how circular references are dealt with in C++. You may need to split this up into two *declarations* of the classes, then implement after. What you're doing here, jamming it all into one file, is part of the problem. These things are generally broken out into separate `.hpp` and `.cpp` files. – tadman Jan 15 '23 at 20:42

1 Answers1

2

You need a forward declaration. Like this

class Spheric; // forward declaration

class Decard
{
    ...
    void ToMe(const Spheric& S); // not defined yet
    ...
};

class Spheric
{
    ...
};

// now Decard::ToMe can be defined
inline void Decard::ToMe(const Spheric& S)
{
    m_x = S.GetR() * sin(S.GetTheta()) * cos(S.GetPhi());
    m_y = S.GetR() * sin(S.GetTheta()) * sin(S.GetPhi());
    m_z= m_x = S.GetR() * cos(S.GetTheta());
}

The foeward declaration allows you to mention the class Spheric but not to use it. So the definition of Decard::ToMe must be postponed until both classes have been fully defined.

john
  • 85,011
  • 4
  • 57
  • 81