Identifying methods within a method

{NOTE sorry if this question is poorly worded, I'm a very basic C++ user.} I want to create a method that either selects one of the arguments in another method i've made, or applicably converts the argument. Let me explain more.

I am writing a simple program which presents vectors in either cartesian or spherical polar space. My cartesian vector looks like this:

{code removed}

And my spherical polar method looks like this:

{code removed}

I have already defined my xcoord, ycoord, xcoord variables in the private section of my class, and this code has all been written in the header file. Also the char unit == r or d is simply to identify between degrees or radian units (also to serve as a dummy variable to prevent overloading).

As you can see, I can now define some simple 3D vectors in my main, in either cartesian or spherical polar without the risk of overloading.

However, I now wish to create an access method which returns the values of theta or phi for either type of vector. This is easy for the cartesian coordinates, and my access method looks as such:

{code removed}

As you can see, the method 'getphi()' will convert the respective cartesian vector into a spherical polar quantity. However, if a vector (lets call it v1) is applied to the method in the main as v1.getphi(), then my code will clearly only work if v1 is cartesian. If v1 is polar, it will use r and theta in the method, clearly wrong.

I want to add a statement, most likely using if/else, which identifies between my vectors as either cartesian or polar. If the vector is polar, instead of having to convert to polar as shown above, I want the method to simply return the coordinate phi or theta with no modification to it (much like it does in the access method for cartesian coordinate section of my code above).

I think I have to exploit the number of arguments in the method 'threevector', but I dont know how to create a statement which recognises if the vector i'm applying to 'getphi()' or 'gettheta()' is either cartesian or polar.

Any help would be fantastic! Thanks!
Last edited on
Why not add a boolean variable to your class: bool isCartesian; ?

In your three argument constructor, set isCartesian = true;
In your four argument constructor, set isCartesian = false;
Then where you need to distinguish, simply test isCartesian.

Am I missing something? It's been a long time since I've dealt with this stuff.




Can I see the full code for the class? I'll be back in haf an hour!
Couldn't you just give the vector type a member letting it know what type it is?

Maybe a boolean or an enum.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class threevector
{
   . . .
   bool isCartesian;
   . . .
};



// Cartesian constructor
threevector(double x, double y, double z)
{
   xcoord = x;
   ycoord = y;
   zcoord = z;

   isCartesian = true;
}


// Spherical Polar constructor
threevector(double r, double theta, double phi, char unit)
{
   . . .
   isCartesian = false;
   . . . 
}

double getPhi
{
   if( isCartesian )
   {
      // Cartesian method
   } 
   else
   {
      // Cartesian flag not set, assume Polar
      // Polar method
   }
}


Jeez, well and truly ninja'd by AbstractionAnon there...
Last edited on
@AbstractionAnon

That sounds like a really neat way of differentiating between them, but I have no idea how boolean variables work lol. What exactly do I need to test isCartesian?

Also @Marcos, here is my full class. Sorry if some of the code seems a little inessential, or lacking coherence, i'm still trying to piece things together

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126

//
//  threevector.h
//  Section 2
//
//  Created by Vito Cientanni on 22/02/2013.
//  Copyright (c) 2013 Vito Cientanni. All rights reserved.
//

#ifndef THREEVECTOR_H  // Prevents the class being re-defined
#define THREEVECTOR_H

#include <iostream> // Include input/output stream
#include <cmath> // Include math library

class threevector
{
private:
    double xcoord, ycoord, zcoord; // Private data members
    
public:
// Default constructor
    threevector()
    {
        xcoord = 0.0;
        ycoord = 0.0;
        zcoord = 0.0;
    }
    
// Cartesian constructor
    threevector(double x, double y, double z)
    {
        xcoord = x;
        ycoord = y;
        zcoord = z;
    }
    
// Spherical Polar constructor
    threevector(double r, double theta, double phi, char unit)
    {
        if (unit == 'r')
        {
            xcoord = r*sin(theta)*cos(phi);
            ycoord = r*sin(theta)*sin(phi);
            zcoord = r*cos(phi);
        }
        
        else if (unit == 'd')
        {
            xcoord = r*sin(theta*(4.0*atan(1.0))/180)*cos(phi*(4.0*atan(1.0))/180);
            ycoord = r*sin(theta*(4.0*atan(1.0))/180)*sin(phi*(4.0*atan(1.0))/180);
            zcoord = r*cos(phi*(4.0*atan(1.0))/180);
        }
        
        else
        {
            std::cout << "Input error: choose units of degrees (d) or radians (r)." << std::endl;
        }
        
    }
    
// Access methods for cartesian coordinates
    double getx()
    {
        return xcoord;
    }
    
    double gety()
    {
        return ycoord;
    }
    
    double getz()
    {
        return zcoord;
    }
// Access methods for spherical coordinates
    double getphi()
    {
        double b = atan(gety()/getz());
        return b;
    }
    
    double gettheta()
    {
        double g = acos(getx()/mag());
        return g;
    }

// Access method for cartesian axial components
    void components()
    {
        std::cout << "Axial components are: "
        << "x = " << getx() << ", "
        << "y = " << gety() << ", "
        << "z = " << getz() << std::endl;
    }
    
// Access methods for magnitude of the vector
    double sqsm()
    {
        double v = (getx()*getx()) + (gety()*gety()) + (getz()*getz());
        return v;
    }
    
    double mag()
    {
        double u = sqrt(sqsm());
        return u;
    }
    
// Method to print out contents to screen
    void print()
    {
        std::cout << xcoord << ", " << ycoord << ", " << zcoord << std::endl;
    }
    
    void print(std::ofstream& fout)
    {
        fout << xcoord << '\t'
             << ycoord << '\t'
             << zcoord << std::endl;
    }
};

#endif // THREEVECTOR_H 
You guys are fantastic, thanks for the help btw
The easy solution (and the cleanest approach) is making your vector class have more private members describing it. A vector should have:

1
2
3
4
5
class threevector
{
private:
    double phi, zeta;             // Private data members, polar data
    double xcoord, ycoord, zcoord; // Private data members, cartesian data 


Whichever constructor user may employ, you get the info for the rest of the variables.
It's easiest this way, and by looking at the code, anyone can understand what a threevector's attributes are.

Last edited on
You don't need any boolean isCartesian to determine whether a threevector is cartesian or spherical polar coordinates since you always store the vector with its xyz coordinates. It doesn't even make sense to ask whether the vector is in Cartesian or spherical polar coordinates. For any vector you can get its coordinates in either coordinate system.

1
2
3
4
5
6
7
8
9
threevector v( 1.0, 2.0, 3.0 );

double x = v.getx();
double y = v.gety();
double z = v.getz();

double phi = v.getphi();
double theta = v.gettheta();
double radius = v.getr(); // You need to add this function to your class 


You need to add the method double threevector::getr() to your class.
I'm assuming that your formulas are correct.

Edit:

I see you already have the equivalent of getr() in mag().
Last edited on
One other thought:
In your constructor threevector(double r, double theta, double phi, char unit) you might want to add tests for uppercase 'D' or 'R'.

if (unit == 'r' || unit == 'R') ... else if (unit == 'd' || unit == 'D') ...

The user of the class shouldn't have to care about upper or lowercase.
If you use the toupper (or tolower) function, you can avoid testing the input twice.

1
2
3
4
5
6
#include <locale>

unit = std::toupper(unit);

if (unit == 'R') {}
else if (unit == 'D'){}


It would also be good if you put the class declaration into a header file, put the implementation (the function definitions) into a .cpp file. The definitions would look like this:

1
2
3
4
5
void threevector::print() {

//your code here

}


Then there would be no need to call get functions like you do on line 102. Member functions have direct access to member variables.

The header file needs to be include in any .cpp file that needs to use that class.

It is a bad idea to include files that have implementation code in them, because they may be included multiple times in an application.

Also there is a convention to name member variables with a leading m_ . This makes it easier for naming parameters & member variables:

1
2
3
4
5
6
threevector(double x, double y, double z)
    {
        m_x = x;
        m_y = y;
        m_z = z;
    }


Obviously you need to change the declaration of the class. You can use find-replace to alter each appearance of xcoord etc in the .cpp file.

I think you should also have functions to convert from degrees to radians and vice versa. At the moment you have code that does that 5 times - it is better to have a function.

There you go - some stuff to have a go at & have fun!!
Topic archived. No new replies allowed.