Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Resolving apparent circular dependency: class A having a method that takes in class B, while class B having a member of type class A

I have two classes that I want to define, Position and TangentVector, partially given as follows:

class Position
{
public:
    Position(double x, double y, double z);
    
    // getters
    double x(){ return m_x };
    double y(){ return m_x };
    double z(){ return m_x };

    void translate(const TangentVector& tangent_vector);
private:
    double m_x;
    double m_y;
    double m_z;
}
class TangentVector
{
public:
    Tangent(double x, double y, double z, Position position);

    // getters
    double x(){ return m_x };
    double y(){ return m_x };
    double z(){ return m_x };
private:
    double m_x;
    double m_y;
    double m_z;
    Position m_position;
}

The key thing to note with the classes is that TangentVector has a member of type Position (TangentVector depends on Position) while Position has a method that takes in an argument of type const TangentVector& (Position depends on TangentVector?).

For context’s sake, Position is intended to represent a point on the unit sphere, and TangentVector describes a vector tangent to the sphere, with the origin of the vector specified by a Position. Since the definition of a VectorTangent requires a Position to be specified, it seems reasonable to say that VectorTangent depends on Position. However, now I want to define a function that takes a Position on the sphere, and "translates" it along the sphere by a direction and distance given by TangentVector. I would really like this translate method to live in the Position class, since it a function that modifies the state of Position. This would lend itself to the following usage, which I feel is fairly natural:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Position position{ 1.0, 0.0, 0.0 };
TangentVector tangent_vector{ 0.0, PI/2, 0.0, position };
position.translate(tangent_vector);                        // Now { 0.0, 1.0, 0.0 };

However, I fear that this results in some circular dependency. So…

  • Is this case an example of circular dependency? Is this case bad practice?
  • If so, how can this circular dependency be avoided? How can this code be modified such that it is in-line with good OOP practices?

(I considered making the Position m_position member a raw pointer instead. In this case, however, I intend m_position to be fully owned by TangentVector, rather than allow the possibility of it being altered external to the class. In the example usage code, I do not want the translate method to modify tangent_vector, which would happen if tangent_vector‘s constructor took in position as a pointer and stored it as a member.)

>Solution :

class Position takes only a reference to class TangentVector. Therefore you might pre-declare TangentVector as class TangentVector; before the declaration of class Position:

class TangentVector;

class Position
{
public:
    Position(double x, double y, double z);
    
    // getters
    double x(){ return m_x };
    double y(){ return m_x };
    double z(){ return m_x };

    void translate(const TangentVector& tangent_vector);
private:
    double m_x;
    double m_y;
    double m_z;
};
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading