#1
  1. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2003
    Posts
    26
    Rep Power
    0

    C++: Creating a member object?


    Assuming I have Class A and Class B, is it possible to have Class B create a private instance of Class A during construction, much like you might create a member variable?

    So, I would declare the instance of Class A in the 'private:' section of Class B's declaration, and initialize it in Class B's constructor?

    Or at least, that is what I am trying to do with no luck.

    (I wasn't going to post the actual code to save space, but looking back over what I wrote above, I don't think it would make sense otherwise):

    Code:
    class DiceRoller {
      public:
        DiceRoller();
        ~DiceRoller();
        vector<string> rollDice(string pool);
      private:  
        void Tokenize(const string &str, vector<string> &tokens, const string &delimiters);
        TRanrotWGenerator myGenerator;  // member object, I think
    };
    
    DiceRoller::DiceRoller() {
      TRanrotWGenerator myGenerator(time(NULL));
    }
    
    DiceRoller::~DiceRoller() {
      
    }
    DiceRoller::rollDice (which I snipped for relevance) needs to use a TRanrotWGenerator object, but since a call to rollDice might be looped in my application, I do not want to create/recreate (and in the case of it being a random number generator, seed/reseed) that TRanrotWGenerator object.

    This is my first C++ application, so feel free to point out the obvious, since I am not familiar with all the idioms of the language.

    It runs just fine if I do create the TRanrotWGenerator object in rollDice, where it is used. But this just doesn't seem clean to me and there must be a more effecient way. This is especially important as I might overload the rollDice method for added functionality -- and there is no need to be repetitious with seeding the generator.
  2. #2
  3. not a fan of fascism (n00b)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Feb 2003
    Location
    ct
    Posts
    2,756
    Rep Power
    95
    yes you can create it in the constructor instead, but there is a special format. lets say you have:
    Class A
    private:
    int x;
    int y;
    public:
    Class_A(int a, int b) { x = a; y = b;}
    and then Class B
    private
    Class_A a_object
    public:
    Class_B(int x_val, int y_val) :
    a_object(x_val, y_val)

    --basically you must call a constructor for each object that is a member of the new class.
  4. #3
  5. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2003
    Posts
    26
    Rep Power
    0
    I think I followed your example, but I don't think the following is correct:

    Code:
    class DiceRoller {
      private:  
        void Tokenize(const string &str, vector<string> &tokens, const string &delimiters);
        TRanrotWGenerator myGenerator;
      public:
        DiceRoller() : myGenerator(time(NULL));
        ~DiceRoller();
        vector<string> rollDice(string pool);
    };
    
    DiceRoller::DiceRoller() {
    
    }
    
    DiceRoller::~DiceRoller() {
      
    }
    So, what do I actually do in the constructor, then? Is the previous close, and I'm just missing some things or did I misread the example?
  6. #4
  7. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,255
    Rep Power
    2222
    I believe you're looking for a member initialization list. It's been a few years, so I've been looking it up, but all of the examples I've seen define the constructor inline or inside the class declaration.

    It's my understanding that the initialization list needs to go with the constructor definition, not with the declaration. But I could be wrong.

    How I think it should be written [EDIT: I hadn't editted something out that I should have; the error is in the comment and the uncommented line should be correct]:
    Code:
    class DiceRoller 
    {
      private:  
        void Tokenize(const string &str, vector<string> &tokens, const string &delimiters);
        TRanrotWGenerator myGenerator;
      public:
    //    DiceRoller() : myGenerator(time(NULL));
        DiceRoller();
        ~DiceRoller();
        vector<string> rollDice(string pool);
    };
    
    DiceRoller::DiceRoller() : myGenerator(time(NULL))
    {
    
    }
    
    DiceRoller::~DiceRoller() 
    {
      
    }
    myGenerator's constructor will run before DiceRoller's does.

    BTW, the order in which member objects are declared determines the order in which they are constructed. The order in which they are put into the member initialization list has no effect on that order. If one object's constructor depends on a second object, then that second object needs to be placed above the first. We actually encountered that problem in a real-life project.
    Last edited by dwise1_aol; June 27th, 2003 at 03:34 PM.
  8. #5
  9. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2003
    Posts
    26
    Rep Power
    0
    Hmm, didn't seem to do the trick.

    Code:
    class DiceRoller {
      private:  
        void Tokenize(const string &str, vector<string> &tokens, const string &delimiters);
        TRanrotWGenerator myGenerator;
      public:
        DiceRoller() : myGenerator(time(NULL));
        vector<string> rollDice(string pool);
    };
    
    DiceRoller::DiceRoller() : myGenerator(time(NULL)) {
    
    }
    Here are the errors:

    Code:
    ../include/DiceRoller.hh:19: function body for constructor missing
    ../include/DiceRoller.hh: In constructor `DiceRoller::DiceRoller()':
    ../include/DiceRoller.hh:19: parse error before `;' token
    ../include/DiceRoller.hh: At global scope:
    ../include/DiceRoller.hh:23: redefinition of `DiceRoller::DiceRoller()'
    ../include/DiceRoller.hh:19: `DiceRoller::DiceRoller()' previously defined here
    ../include/DiceRoller.hh:23: no `DiceRoller::DiceRoller()' member function 
       declared in class `DiceRoller'
    ../include/DiceRoller.hh:24: confused by earlier errors, bailing out
    But now I'll try and look up "member initialization list" since you gave me a name for what I want.
  10. #6
  11. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2003
    Posts
    26
    Rep Power
    0
    See, all I needed to know was what I was trying to do. Heh.

    This works:

    Code:
    class DiceRoller {
      private:  
        void Tokenize(const string &str, vector<string> &tokens, const string &delimiters);
        TRanrotWGenerator myGenerator;
      public:
        DiceRoller();
        vector<string> rollDice(string pool);
    };
    
    DiceRoller::DiceRoller() : myGenerator(time(NULL)) {
      
    }
    Googled for "Member Initialization Lists" and found what I needed.

    Thanks for the help.
  12. #7
  13. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,255
    Rep Power
    2222
    Oops! I was in a hurry and didn't edit out the initialization inside the class declaration. What you ended up doing was what I was trying to write.

    Sorry about that. At least it led to the solution.
  14. #8
  15. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2003
    Posts
    26
    Rep Power
    0
    Definitely thanks, dwise. With your example and the one I found after you pointed out "Member Initialization Lists", I understood.

IMN logo majestic logo threadwatch logo seochat tools logo