Thread: On declaring classes. (Newbie)

  1. #1
    Registered User
    Join Date
    Jan 2005
    Posts
    106

    On declaring classes. (Newbie)

    Er, okay.

    I have two classes: A and B.

    Class B must container a member which is a class A object. Class A must contain a member that's a class B object.

    How do I declare these so that I don't get errors?

  2. #2
    vae victus! skorman00's Avatar
    Join Date
    Nov 2003
    Posts
    594
    I'll give you some hints:
    forward declarations
    OR
    change where the #include statements are placed

  3. #3
    Registered User
    Join Date
    Jan 2005
    Posts
    106
    Eh, what's a forward declartion? Is that just a class name; thing? I tried doing that and i think I got an error, but...

  4. #4
    Toaster Zach L.'s Avatar
    Join Date
    Aug 2001
    Posts
    2,686
    Show us what you did. Also, think about the logic behind having a circular dependence like that, and what it means (hint: it comes out bad). Use a pointer or reference to one (or both) of the objects if possible, instead of actual instances.
    The word rap as it applies to music is the result of a peculiar phonological rule which has stripped the word of its initial voiceless velar stop.

  5. #5
    Registered User
    Join Date
    Sep 2004
    Posts
    39
    Zack L. could you give an example of doing this? TIA

  6. #6
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    As Zach pointed out, this leads to infinite dependence, or whatever you call it.

    Class A's constructor constructs an object of class B. But class B's constructor constructs an object of class A. Therefore, you'll get an infinite number of objects of class A and B being constructed.

    >>could you give an example of doing this?
    Very simply, instead of:
    Code:
    class B;  //forward declaration
    
    class A
    {
    public:
       //...
    protected:
       B member;  //holds a B, which...
    };
    
    class B
    {
    public:
       //...
    protected:
       A member;  //holds an A, which...  (see above)
    };
    You can have it hold pointers to each other:
    Code:
    class B;  //forward declaration
    
    class A
    {
    public:
       A() :member(this) {}  //Pass a pointer to myself when constructing B 
    protected:
       B member;  //Holds a B, which...
    };
    
    class B
    {
    public:
       B(A* parent) :member_parent(parent) {}
    protected:
       A* member_parent;  //Holds a pointer to the A that it belongs to
    };
    That's an example of one thing you can do, though without further information I have no idea exactly what the original poster's intention was in having each contain an object of the other.
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  7. #7
    Registered User
    Join Date
    Sep 2004
    Posts
    39
    Once I have multiple objects created, I need to be pick and object and then grab a specific material for it. Lets say I grab the steelBall and need to get the info from the mat class for the steel material or glassCup and need to grab the glass material from the mat class. The way i am trying to do this is in the obj class have a variable, matID, and compare it to the matID in the mat class. Hope i explained this well enough.

    Code:
    #include <math.h>
    #include <vector>
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    const double gravity = 9.8;
    
    //Object Class
    class obj
    {
    public:
    	string objName;
                    double matID;
    	double objMass;
    	bool objRoll;
    };
    
    class mat
    {
    public:
                    double matID;
    	double objWeight;
    	double objDensity;
    }
    
    int main()
    {
    obj steelBall, glassCup;
    mat steel, glass;
    
    steelBall.matID = 0;
    steelBall.mass = 5;
    
    steel.matID = 0;
    steel.weight = 3;
    steel.density = 5;
    
    glassCup.matID = 1;
    glassCup.mass = 3;
    
    glass.matID = 1;
    glass.weight = 2;
    glass.density = 2;
    
         return 0;
    }//end main()

  8. #8
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    Better yet, you can use pointers:
    Code:
    class mat;  //forward declaration
    
    class obj
    {
    public:
        string objName;
        mat* material;
        double objMass;
        bool objRoll;
    };
    
    ...
    
    obj steelBall, glassCup;
    mat steel, glass;
    
    steelBall.material = &steel;  //material now points to steel
    steelBall.mass = 5;
    
    steel.matID = 0;
    steel.weight = 3;
    steel.density = 5;
    
    ...
    
    std::cout << "The density of the Steel Ball is " << steelBall.material->density << "." << std::endl;
    That saves you the trouble of trying to match up ID's every time you want to calculate something using information from the material.
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  9. #9
    Registered User
    Join Date
    Sep 2004
    Posts
    39
    Thank you so much for the help. Hope this helps the person who orginally started this post.

  10. #10
    Toaster Zach L.'s Avatar
    Join Date
    Aug 2001
    Posts
    2,686
    In Hunter2's example, a reference would work as well (this is a personal preference, but in this case, it is the solution that I would prefer).

    In either case (pointer or reference), you have to make sure that your material object does not go out of scope at any point. (If you just used an object, it would simply be copied -- make sure appropriate copy ctor and operator= is defined.)

    One type of solution would be to make a singleton class, a 'MaterialRegistry'. Essentially, it would allow you to construct a material object, and key it to, say, a specific name. Then, if you want steel, you ask the registry object for the material data for 'steel', and if it has the data, it gives it to you. If it didn't, you could deal with it as you saw fit.

    What this solution allows you to do is to avoid replicating data for a specific material, which avoids the necessity of hard-coding (or even reading in) data in multiple places throughout your code.

    Here is a reference I found on design patterns: http://home.earthlink.net/~huston2/dp/patterns.html
    I haven't thoroughly checked over the site, but it looks fairly decent. They have the singleton pattern on there, and looking at the other 'Creational Patterns' probably give you a decent idea about where I was headed with the idea of a registry.

    Anyway, if you are interested in OO design like this, I also recommend the Design Patterns book.
    The word rap as it applies to music is the result of a peculiar phonological rule which has stripped the word of its initial voiceless velar stop.

  11. #11
    Registered User
    Join Date
    Jan 2005
    Posts
    106
    Code:
    class B
    {
    public:
       B(A* parent) :member_parent(parent) {}
    protected:
       A* member_parent;  //Holds a pointer to the A that it belongs to
    };
    Hm. I'm going to assume that the constructor does something important, because just having something like A *member_parent gives me a "syntax error before *" message. What exactly IS the :member syntax after the function prototype anyway? I've never seen that before. What does it do?

  12. #12
    Toaster Zach L.'s Avatar
    Join Date
    Aug 2001
    Posts
    2,686
    You need a forward declaration of A:
    Code:
    class A;
    
    class B
    {
    public:
       B(A* parent) :member_parent(parent) {}
    protected:
       A* member_parent;  //Holds a pointer to the A that it belongs to
    };
    The word rap as it applies to music is the result of a peculiar phonological rule which has stripped the word of its initial voiceless velar stop.

  13. #13
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    >>What exactly IS the :member syntax after the function prototype anyway?
    When a class contains member variables, and an instance of the class is created (an object of the class), all of its member variables must also be created - and if one of the member variables is an object of another class, it must be constructed. :member(something) simply tells the constructor that when constructing 'member', you should pass (something) to its constructor. So:

    B(A* parent) :member_parent(parent) {}

    The constructor of B takes an A*, and we'll name it 'parent'. Now, when B's constructor is called, i.e. it's being constructed, it will construct member_parent which is an A* by passing the A* constructor 'parent'. Since a pointer is a POD type, the 'constructor' of A* is automatically created, and all it does is copy the value passed to it into itself. So what happens is the value stored in 'parent' is copied into member_parent when B's constructor is called.

    Another example:
    Code:
    class B
    {
    public:
       B(int arg1, int arg2)
       {
    	  x = arg1;
    	  y = arg2;
       }
    protected:
       int x;
       int y;
    };
    
    class A
    {
    public:
       A() :bObject(5, 6), bObject2(1, 2)
       {
       }
    
    protected:
       B bObject;
       B bObject2;
    };
    So in A's constructor, bObject is constructed by passing the values 5 and 6 to its constructor, and bObject2 is constructed by passing the values 1 and 2 to its constructor.
    Last edited by Hunter2; 01-30-2005 at 02:04 PM.
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  14. #14
    Registered User
    Join Date
    Jan 2005
    Posts
    106
    Dev-C++ isn't letting me do forward declarations. Do I need to put them somewhere special?

  15. #15
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    Well, what errors are you getting? And what's your code?
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Does declaring classes in the wrong order matter?
    By Swordsalot in forum C++ Programming
    Replies: 5
    Last Post: 11-27-2005, 12:03 AM
  2. im extreamly new help
    By rigo305 in forum C++ Programming
    Replies: 27
    Last Post: 04-23-2004, 11:22 PM
  3. Prime Number Generator... Help !?!!
    By Halo in forum C++ Programming
    Replies: 9
    Last Post: 10-20-2003, 07:26 PM
  4. include question
    By Wanted420 in forum C++ Programming
    Replies: 8
    Last Post: 10-17-2003, 03:49 AM
  5. Newbie question about the Private type in classes
    By Ryeguy457 in forum C++ Programming
    Replies: 1
    Last Post: 09-07-2002, 10:17 PM