Thread: class structure question

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

    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
    28,413
    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.
    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

  3. #3
    Registered User
    Join Date
    Feb 2003
    Posts
    596
    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
    28,413
    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.
    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

  5. #5
    Registered User
    Join Date
    Feb 2003
    Posts
    596
    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
    838
    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
    596
    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
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    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
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  9. #9
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    838
    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
    596
    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
    838
    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
    596
    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
    838
    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, 05: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, 09:40 PM
  3. Quick question about class template
    By merixa in forum C++ Programming
    Replies: 5
    Last Post: 12-06-2005, 11:43 PM
  4. Replies: 3
    Last Post: 10-31-2005, 12:05 PM
  5. question about .net to 6.0 change causing errors
    By jverkoey in forum C++ Programming
    Replies: 17
    Last Post: 03-23-2004, 10:45 AM