CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 11 of 11
  1. #1
    Join Date
    Aug 2009
    Posts
    68

    General Object-Orientated Question

    Hello,

    I have a very general question about object-orientation programming. I have been programming for a few years, but I'm just wondering what the best practice is for this particular situation.

    Suppose that I have a class, which contains an object of a second class. When I want to update the member variables of the second class, should I update these variables directly from the main program loop, or should I update them indirectly from a function in the first class?

    For example, consider a class "Person", which has an object of type "Age" as a member variable. In my main program loop, each loop represents one day in the life of the person, and so in each loop I want to increase the age of the person by one day. One method for doing this is to directly change the number of days and years from the main program loop. A second method is to call a function in Person, which then directly changes the number of days and years. The third method is to call this function in Person, which then calls a function in Age, which itself changes the number of days and years.

    Below are the three ways I have described, but which is the best one? The first approach is the fastest, but is less elegant. The third approach makes the code the most readable, but if there are lots of embedded classes within each other, this seems quite an inefficient method. So I'm just wondering, in the case of lots of embedded classes, how far down do you go before you access the data directly, rather than calling lots of functions?

    Thanks!

    Method 1 (direct)
    Code:
    class Age
    {
    public:
         int num_days;
         int num_years;
    
         Age() : num_days(0), num_years(0)
    };
    
    class Person
    {
    public:
    
         Age age;
    };
    
    int main()
    {
         Person david;
         int total_num_days = 1000;
    
         for (int i = 0; i < total_num_days; i++)
         {
              david.age.num_days++;
    
              if (david.age.num_days % 365 == 0)
              {
                   david.age.num_years++;
              }
    
              // Do some other stuff for that day
         }
    
         return 0;
    }
    Method 2 (semi-direct)
    Code:
    class Age
    {
    public:
         int num_days;
         int num_years;
    
         Age() : num_days(0), num_years(0)
    };
    
    class Person
    {
    public:
    
         Age age;
    
         void AddDay()
         {
              age.num_days++;
    
              if (age.num_days % 365 == 0)
              {
                   age.num_years++;
              }
         };
    };
    
    int main()
    {
         Person david;
    
         int total_num_days = 1000;
    
         for (int i = 0; i < total_num_days; i++)
         {
              david.AddDay();
    
              // Do some other stuff for that day
         }
    
         return 0;
    }
    Method 3 (indirect)
    Code:
    class Age
    {
    public:
         int num_days;
         int num_years;
    
         Age() : num_days(0), num_years(0)
    
         AddDay()
         {
              age.num_days++;
    
              if (age.num_days % 365 == 0)
              {
                   age.num_years++;
              }
         }
    };
    
    class Person
    {
    public:
    
         Age age;
    
         void AddDay()
         {
              age.AddDay();
         };
    };
    
    int main()
    {
         Person david;
         int total_num_days = 1000;
    
         for (int i = 0; i < total_num_days; i++)
         {
              david.AddDay();
    
              // Do some other stuff for that day
         }
    
         return 0;
    }

  2. #2
    GCDEF is offline Elite Member Power Poster
    Join Date
    Nov 2003
    Location
    Florida
    Posts
    12,635

    Re: General Object-Orientated Question

    #3 is the best design. Basically you want to hide the implementation and rely on an interface to access the object's data. That way you can change the implementation of the class without changing how it's used. It's also generally safer not to access an object's member variables directly. For example, if days had a limit of way 365, you wouldn't want to allow a user to set days to an invalid value. Your SetDays method could control what values days contains and set the days and years appropriately.

  3. #3
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: General Object-Orientated Question

    Yes, but num_days and num_years in class Age should be private as well as age in class Person. This makes sure the object's member variables cannot be access directly as recommended by GCDEF in post #2

  4. #4
    Join Date
    May 2009
    Posts
    2,413

    Re: General Object-Orientated Question

    Quote Originally Posted by karnavor View Post
    The first approach is the fastest, but is less elegant. The third approach makes the code the most readable, but if there are lots of embedded classes within each other, this seems quite an inefficient method.
    This is only an assumption and it's usually wrong. Encapsulation lowers complexity which allows the compiler to produce better code. It's a win-win situation. In addition to more reliable and easy to maintain code, good design also leads to efficient code.
    Last edited by nuzzle; March 2nd, 2013 at 01:19 AM.

  5. #5
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: General Object-Orientated Question

    how far down do you go before you access the data directly, rather than calling lots of functions?
    The good practice recommendation is that you don't access the data directly. Outside of the class, only class methods are used as per post #2 and #4. Only external method interfaces to the class are declared as public. The rest are private as post #3.

  6. #6
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: General Object-Orientated Question

    The first approach is the fastest, but is less elegant. The third approach makes the code the most readable, but if there are lots of embedded classes within each other, this seems quite an inefficient method.
    Don't assume until you tried it.
    For inline functions, the compiler will optimize this so that the binary does the same as directly changing the variable.
    Meanwhile you get the benefit of a better design.


    That said. All 3 approaches are valid. And there may be considerations other than "best design from a pure c++ perspective" that prefer one approach over the other. If you have some kind of databinding mechanism in your program then direct access to the variables (or pointer/reference to them) may be required in that case accessor functions tend to be cumbersome. You could expose the databinding through an additional member, but again, that may have it's own issues.

    Long story short: unless you have a good reason not to. you typically want to go with the best design paradigms, because that gives you the most benefits long term.

  7. #7
    Join Date
    Jul 2002
    Location
    Portsmouth. United Kingdom
    Posts
    2,727

    Re: General Object-Orientated Question

    but if there are lots of embedded classes within each other, this seems quite an inefficient method.
    Don't try to second guess the compiler.

    I once wrote a set of image container classes with associated iterators. The iterators were based on a class heirarchy about four levels deep, with the base class implementing the iterator in terms of a pointer.

    In tests, with full optimisation, there was no discernable difference in performance between accessing the image data with the iterators and a raw pointer.
    "It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
    Richard P. Feynman

  8. #8
    Join Date
    Mar 2013
    Posts
    5

    Re: General Object-Orientated Question

    If you're having trouble storing and reusing objects in C++ I'd check out one of the blogs on this board I made. It could be useful for your development. http://www.verious.com/board/AKumar/...jects-reusing/

  9. #9
    GCDEF is offline Elite Member Power Poster
    Join Date
    Nov 2003
    Location
    Florida
    Posts
    12,635

    Re: General Object-Orientated Question

    Quote Originally Posted by ak223 View Post
    If you're having trouble storing and reusing objects in C++ I'd check out one of the blogs on this board I made.
    That wasn't actually the problem he was having at all.

  10. #10
    Join Date
    Mar 2013
    Posts
    5

    Re: General Object-Orientated Question

    Yeah, I just decided to throw it out there and see if it was useful to him at all.

  11. #11
    Join Date
    Jan 2010
    Posts
    1,133

    Re: General Object-Orientated Question

    I'm with OReubens on this one - assuming that in real code all the classes are properly encapsulated, there's no universally correct design; you can pick any of the above, and your choice will depend almost entirely on the nature of the system you're modeling, and relationships within it. In the sense that, depending on the way you decided to represent whatever it is that you're trying to model, you'll decide in what ways various objects can interact, what should be visible/accessible from where, etc. Design Patterns offer standard (but flexible) solutions to specific families of problems, so check them out, and there are various larger in scope architectural patterns/styles as well. Generally, you would first spend some time and put in some effort in order to understand what makes that system tick, how are various parts of it related, what is the business logic; somewhere along the way you'd start thinking about various ways to represent that system as an OO program (there could be several good candidate representations), and come up with what's called a logical design - a higher level model of the system, not concerned too much with a particular implementation language. Then you'd consider how to go about implementing it, and factor in language, library, platform and hardware specific details (as required), which might result in some design changes to either take advantage of something, or to avoid potential pitfalls. And after that the iterative process goes on - things aren't set in stone, so there might be more design revisions, refactorings, etc., before the project is completed.

    If your question was, however, about encapsulation, generally speaking, data members of a class should never be directly manipulated by objects of a different class (even if the other class is a subclass of the first - most people will agree); so in that context, you should go with Method 3, but make all the state private, and provide manipulation functions, getters and setters, as required - unless you want to leave open a possibility for some sneaky, hard-to-find bugs.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured