class structure question

This is a discussion on class structure question within the C++ Programming forums, part of the General Programming Boards category; Is there a sensible way to achieve something like this: An instance of class M instantiates one of class S-1 ...

  1. #1
    Registered User
    Join Date
    Feb 2003
    Posts
    595

    class structure question

    Is there a sensible way to achieve something like this:

    An instance of class M instantiates one of class S-1 and one of class S-2, and...
    I want S-1 to be able to call methods of M,
    S-2 to be able to call methods of S-1,
    and M to be able to call methods of both S-1 and S-2.

    These classes are otherwise unrelated -- no inheritance.

    Alternatively, I could combine S-1 into M (just replace the S-1 methods and data with M methods and data) but then I would need S-2 (which is declared by M) to be able to call M methods (and M to be able to call S-2 methods).

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,310
    Well, obviously M can call the (public) methods (or rather, member functions) of S-1 and S-2. To allow S-1 to call the (public) member functions of M, you may need to pass a reference or pointer to the M object to the S-1 object instantiated. For S-2 to call the (public) member functions of S-1, you may need to pass a reference or pointer to the S-1 object.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Feb 2003
    Posts
    595
    Quote Originally Posted by laserlight View Post
    ... you may need to pass a reference or pointer to the S-1 object.
    Yes, I forgot to mention that I was hoping to avoid that. Is there any way to avoid that?

    Or can you think of any other (non-class?) structure to replace the S-1 class that would serve as an interface making member functions of M accessible from other classes that are instantiated by M.

    The point is that everything in M is (robot) platform-specific and provides access to the hardware. S-2, etc, would contain code that should be portable to other platforms (given appropriate interfaces). The OS requires that M be the primary object which instantiates S-2, and not the other way around.

    Any ideas?

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,310
    The point is that everything in M is (robot) platform-specific and provides access to the hardware. S-2, etc, would contain code that should be portable to other platforms (given appropriate interfaces).
    What's S-1 for?

    The OS requires that M be the primary object which instantiates S-2, and not the other way around.
    That's fine though. As I mentioned, you can pass a reference or pointer to M to S-2.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    Registered User
    Join Date
    Feb 2003
    Posts
    595
    S-1 (e.g.) is just to encapsulate a particular subset of M functions -- to help avoid having individual developers continually stepping on each other's work.

    As to the pointers, it seemed a little 'inelegant' but I guess we can live with it.

  6. #6
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    839
    Quote Originally Posted by R.Stiltskin View Post
    Is there a sensible way to achieve something like this:

    An instance of class M instantiates one of class S-1 and one of class S-2, and...
    I want S-1 to be able to call methods of M,
    S-2 to be able to call methods of S-1,
    and M to be able to call methods of both S-1 and S-2.

    These classes are otherwise unrelated -- no inheritance.

    Alternatively, I could combine S-1 into M (just replace the S-1 methods and data with M methods and data) but then I would need S-2 (which is declared by M) to be able to call M methods (and M to be able to call S-2 methods).
    you could use pointers to member functions
    or declare M *m as a member of S-1
    and S-1 *s1 as a member of S-2
    and S-1 *s1 and S-2 *s2 as members of M

    and make sure the methods you want to access are public.

  7. #7
    Registered User
    Join Date
    Feb 2003
    Posts
    595
    Hmmm ... it seemed easy until I tried to give s_1 a pointer to m. g++ gives
    classtest1.h:17: "error: 'm' was not declared in this scope".

    which makes sense, since each header file refers to the other. Can you see a way to get around this?


    classtest.h:
    Code:
    #ifndef _classtest_h
    #define _classtest_h
    
    #include "classtest1.h"
    #include "classtest2.h"
    #include <iostream>
    using namespace std;
    
    
    class m {
    public:
      m() { one.setnum(6); two.setone(&one); one.setbody(this)}
      void print1() {
        one.print();
      }
      void print2() {
        two.print();
      }
      void print3() {  
        cout << "hello from m" << endl;
      }
    private:
      s_1 one;
      s_2 two;
      int i;
    };
    
    #endif

    classtest1.h:
    Code:
    #ifndef _classtest1_h
    #define _classtest1_h
    
    #include "classtest.h"
    #include <iostream>
    using namespace std;
    
    class s_1 {
    public:
      void print () {
        cout << "s_1 secretnum = " << secretnum << endl;
        body->print3();
      }
      void setnum(int x){
        secretnum = x;
      }
      void setbody(m* _body) {
        body = _body;
      }
    private:
      int secretnum;
      m* body;
    };
    
    #endif
    classtest2.h:
    Code:
    #ifndef _classtest2_h
    #define _classtest2_h
    
    #include "classtest1.h"
    #include <iostream>
    using namespace std;
    
    
    class s_2 {
    public:
      void setone(s_1* _one) {
        one = _one;
      }
      void print() {
        cout << "s_2 calling s_1" << endl;
        one->print();
      }
    private:
      s_1* one;
    };
    
    #endif
    classtest.cc
    Code:
    #include "classtest.h"
    #include "classtest1.h"
    #include "classtest2.h"
    #include <iostream>
    using namespace std;
    
    //slave1 one;
    
    int main () {
      m rex;
      rex.print1();
      rex.print2();
      return 0;
    }

  8. #8
    CSharpener vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,449
    use forward declarations to avoid unneded dependencies like

    Code:
    #ifndef _classtest2_h
    #define _classtest2_h
    #include <iostream>
    
    class s_1;
    
    class s_2 {
    public:
      void setone(s_1* _one) {
        one = _one;
      }
      void print() {
        std::cout << "s_2 calling s_1" << std::endl;
        one->print();
      }
    private:
      s_1* one;
    };
    
    #endif
    never put using directive into header
    you will probably need to move the print function implementaion into cpp file
    The first 90% of a project takes 90% of the time,
    the last 10% takes the other 90% of the time.

  9. #9
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    839
    a good way to avoid header file cross referencing is to separate your classes into header files and cpp files and use forward declarations

    in header file:


    Code:
    class S_1;
    class M
    {
    // declarations...
        S_1 *s1;
    };
    then in the cpp file, where you delcare the method bodies, do: #include "S_1.h"
    Last edited by m37h0d; 03-20-2008 at 03:41 PM.

  10. #10
    Registered User
    Join Date
    Feb 2003
    Posts
    595
    I still had to #include the s_1 and s_2 headers in m's header file. When I tried with forward declarations I got "incomplete type" errors for m's 'one' and 'two' data members.

    But the other two headers were ok with just forward declarations, and now the whole thing compiles & runs correctly.

    Thanks for the help.

  11. #11
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    839
    Quote Originally Posted by R.Stiltskin View Post
    I still had to #include the s_1 and s_2 headers in m's header file. When I tried with forward declarations I got "incomplete type" errors for m's 'one' and 'two' data members.

    But the other two headers were ok with just forward declarations, and now the whole thing compiles & runs correctly.

    Thanks for the help.
    it sounds like you're delcaring S_1 s1 and not S_1 *s1.


    you have to use a pointer in forward declarations. this works because pointers are always 32bts, but when declaring an actual instance of the class as a member, it has to know exactly how much memory to allocate.

  12. #12
    Registered User
    Join Date
    Feb 2003
    Posts
    595
    Quote Originally Posted by m37h0d View Post
    it sounds like you're delcaring S_1 s1 and not S_1 *s1.
    Exactly.

    Thanks for the explanation.

  13. #13
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    839
    Quote Originally Posted by R.Stiltskin View Post
    Exactly.

    Thanks for the explanation.
    be sure to split your classes into h files, containing only declarations, and cpp files containing the implementations, and do your #includes to any non-descendant (you can't do a forward declaration for a base class) classes in the cpp file.

    this will avoid a lot of headaches with header conflicts

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 8
    Last Post: 01-13-2008, 04:57 PM
  2. n00b question regarding the Map Class in the STL library
    By Axegrinder#9 in forum C++ Programming
    Replies: 2
    Last Post: 12-17-2005, 08:40 PM
  3. Quick question about class template
    By merixa in forum C++ Programming
    Replies: 5
    Last Post: 12-06-2005, 10:43 PM
  4. Replies: 3
    Last Post: 10-31-2005, 11:05 AM
  5. question about .net to 6.0 change causing errors
    By jverkoey in forum C++ Programming
    Replies: 17
    Last Post: 03-23-2004, 09:45 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21