Thread: Cross dependant classes

  1. #1
    Registered User ~Kyo~'s Avatar
    Join Date
    Jun 2004
    Posts
    320

    Cross dependant classes

    Should I make a handler class or something? Since the compiler hates this cross dependancy, but I would like both classes to be able to handle the collision detection.

    Code:
    #ifndef C_RECT_H
    #define C_RECT_H
    
    #include "C_Circ.h"
    
    class C_Rect
    {
        public:
             C_Rect();
             C_Rect(int X,int Y,int SX,int SY);
        void Set_Attribs(int X,int Y,int SX,int SY);
        bool Collision_Test(C_Circ);
        bool Collision_Test(C_Rect);
    
        int  Get_X();
        int  Get_Y();
        int  Get_SX();
        int  Get_SY();
    
        private:
        int x;
        int y;
        int sx;
        int sy;
    
    };
    
    #endif // C_RECT_H
    Code:
    #ifndef C_CIRC_H
    #define C_CIRC_H
    
    #include "C_Rect.h"
    
    class C_Circ
    {
        public:
    
             C_Circ();
             C_Circ(int X,int Y,int R);
        void Set_Attribs(int X,int Y,int R);
        bool Collision_Test(C_Circ);
        bool Collision_Test(C_Rect);
    
        int  Get_X();
        int  Get_Y();
        int  Get_R();
    
        private:
        int x;
        int y;
        int rad;
    
    };
    
    #endif // C_CIRC_H_INCLUDED

  2. #2
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Perhaps having an actual base class that handles stuff as collisions would be a good idea?
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #3
    The larch
    Join Date
    May 2006
    Posts
    3,573
    In such situations you'd generally use forward declarations. Instead of including the whole header, put
    Code:
    class C_Circ;
    class C_Rect;
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    That doesn't feel like it's a good idea. It will introduce class dependencies, and thinking about it, why should a Circle know about a Rect and vice versa?
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #5
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    The context is one of two shapes deciding if they intersect.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  6. #6
    Registered User
    Join Date
    Aug 2011
    Location
    Montreal, Quebec, Canada
    Posts
    73
    Look up inheritance and maybe even polymorphism.

    Inheritance is when you set it so that one or more classes derive from another.
    Polymorphism is some way to use the more generic class to control some behaviour of the more specific classes.

    Suppose:

    Code:
    class Shape { };
    class Square : public Shape { };
    class Circle : public Shape { };
    
    std::vector<Shape*> shape_list;
    std::vector<Shape*>::iterator it;
    
    for(it = shape_list.begin(); it != shape_list.end(); it++) {
        // do stuff with this shape
        Shape* p = NULL;
        if((p = dynamic_cast<Circle*>(*it)) != NULL) { }
        if((p = dynamic_cast<Square*>(*it)) != NULL) { }
    }
    I'm just not certain it really is dynamic_cast that is to be used in this case. I haven't used those kind of casts in a long time (dynamic/static/reinterpret/const_cast<>).

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    dynamic_cast should not be used here. dynamic_cast is used to "upcast" classes, that is, case the type from a base class to a derived class. But that will not solve the problem.
    Having to classes "know" each other is bad idea. Not only will it introduce dependencies on all the other objects, which will cause a recompile of all classes if you modify one, but it will also force you to implement Nē functions where N is the number of shapes.
    For each shape you add, you have to add a new function to test against this new shape in the existing classes and add functions in the new class. If you count, that will add up to Nē.

    One idea is to create some kind of collision manager. But this brings up the exact same problem. You have to implement Nē functions to test collisions.
    This is exactly why polymorphism was invented. You can create one function that will test collision between two shape objects. This means you should have a common base class for collision (and probably other things, as well).
    The base class could either contain a virtual method for getting collision data, or store some kind of collision data in the base class. The later is probably cheaper, but may take more memory.
    But if you implement this, then it seems pointless to have a collision manager since the base class could implement the collision testing.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    Registered User
    Join Date
    Sep 2011
    Posts
    5
    Quote Originally Posted by ~Kyo~ View Post
    Should I make a handler class or something? Since the compiler hates this cross dependancy, but I would like both classes to be able to handle the collision detection.

    Code:
    #ifndef C_RECT_H
    #define C_RECT_H
    
    #include "C_Circ.h"
    
    class C_Rect
    {
    };
    
    #endif // C_RECT_H
    Code:
    #ifndef C_CIRC_H
    #define C_CIRC_H
    
    #include "C_Rect.h"
    
    class C_Circ
    {
    };
    
    #endif // C_CIRC_H_INCLUDED

    If you have a dependency like this:

    class A <--> class B
    just use your nomal "includes" at the beginning with appropriate precompiler "ifndefs" like you showed it before and take care of the linker.

    The linker just adds new stuff that is already needed by previous parts of the code. which means you have to link your code after compiling like this:
    linker classA.o classB.o classA.o

    If you want to compile a single file without linking it (for example in a makefile) just use the "-c" option of your compiler. the compiler just checks for appropriate declarations in the "#include" files and everything works out.



    Axl

  9. #9
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Axl
    If you have a dependency like this:
    class A <--> class B
    just use your nomal "includes" at the beginning with appropriate precompiler "ifndefs" like you showed it before and take care of the linker.
    Generally, that circular inclusion will not work, and if it does work, it is because one of the header inclusions was not necessary in the first place.

    Take ~Kyo~'s example: suppose we compile a translation unit that includes C_Rect.h. Now, C_Rect.h includes C_Circ.h which includes C_Rect.h. The second include of C_Rect.h effectively does not happen due to the header inclusion guards. Well and good. However, C_Circ.h still needs the declarations and definitions from C_Rect.h. Since C_Rect.h was not included, there would be compile errors, so we never get to take care of the linker. But if C_Circ.h does not need any declaration or definition from C_Rect.h, there would not be a problem... but then we would not have needed to include C_Rect.h in C_Circ.h to begin with.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Determine dependant dlls
    By sid-mark in forum Tech Board
    Replies: 3
    Last Post: 04-25-2011, 10:50 AM
  2. Inter-dependant classes
    By Colin_theRobot in forum C++ Programming
    Replies: 8
    Last Post: 04-03-2006, 12:08 PM
  3. Cross-Referencing Classes
    By XSquared in forum C++ Programming
    Replies: 4
    Last Post: 12-08-2002, 05:42 PM
  4. What does implementation-dependant mean?
    By Gamma in forum C++ Programming
    Replies: 1
    Last Post: 04-19-2002, 06:56 PM
  5. How CProgramming dependant are you :)?
    By Carlos in forum A Brief History of Cprogramming.com
    Replies: 0
    Last Post: 09-17-2001, 09:16 AM