Thread: Why Use Objects?

  1. #1
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665

    Why Use Objects?

    As a pretty decent C user, I'm just wondering what's the point of an object. What does an object do that I couldn't just write out in C? Is it for readability only?

    There's one application I think that might be useful. I play DotA so there's 100 characters, each with 4 abilities. You could create an object to represent each hero and they'd have generic function pointers that would be initialized to point at a specific library function (each hero's specific ability). Or maybe the pointers would make it easier to write code that would allow the function to be called from the structure itself. I don't really know.

    So why should I care about objects?

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    What is an "object"?

    In C, an object is a "region of data storage in the execution environment, the contents of which can represent values". Objects have been useful in pretty much every C program that I have ever written. So, why should you not care about objects?

    Or, perhaps you are talking about "object oriented programming" as a programming paradigm, in which case these articles may be of interest to you:
    The Open-Closed Principle
    The Liskov Substitution Principle
    The Dependency Inversion Principle
    The Interface Segregation Principle
    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
    May 2012
    Posts
    505
    You use objects when you have things that behave differently but similarly to the same impetus. So an automobile, a bicycle, a train and an articulated truck all brake. The braking always reduces speed. But the details vary.
    So a programming example would be a "stream". A stream is something that accepts a sequence of characters (for the sake of argument). It could just discard them ( a null steam), it could write them out to disk, it could print them on the screen, it could store them in a string. If we want to write the program "hello world" we can pass the characters to any stream. We could even implement our own custom stream that capitalises all words.
    There are lots of examples like this. GUI components, lines, geometric shapes, big integers, image buffers and so on.
    I'm the author of MiniBasic: How to write a script interpreter and Basic Algorithms
    Visit my website for lots of associated C programming resources.
    https://github.com/MalcolmMcLean


  4. #4
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Malcolm, would you be willing to elaborate what you said about geometric shapes and big integers?

    Also, I have seen an object as a solution to certain if-statements. Expanding upon what you said, all those mechanical devices brake but they do it differently. So instead of checking the type of structure with an if, you could just call the brake function in the object.

  5. #5
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Also, I have seen an object as a solution to certain if-statements.
    If you're talking about the anti-if movement, I don't really see a reason to take it seriously. However, I agree that code shouldn't exceed a certain vertical width. Once you get to about 3 indentation levels, you need to think about refactoring. Refactoring does apply to C as much as it applies to C++. See below.

    Expanding upon what you said, all those mechanical devices brake but they do it differently. So instead of checking the type of structure with an if, you could just call the brake function in the object.
    As a procedural language, C works best when you have your program organized into small functions encapsulating each task. When that task involves data, you can improve the interface by organizing data into one or several structures (as discussed here). If your methods get really long, like say more than one page, or you indent really far out vertically, then you need to think about breaking out parts of the function into smaller functions.
    Last edited by whiteflags; 06-06-2013 at 04:37 PM.

  6. #6
    Registered User migf1's Avatar
    Join Date
    May 2013
    Location
    Athens, Greece
    Posts
    385
    The Object Oriented Paradigm (OOP) may be -and usually is- of great help when developing medium to large scale projects. Mainly because it actually forces us to plan and organize our project long before start coding it. For small projects, this approach may seem (and it often is) a waste of time and energy.

    Although there are lots of areas that are not suitable for modeling them using OOP (this is a classic anti-OOP link, please take it with a pinch of salt) still there are lots of areas that OOP fits very nicely (some of them already listed my Malcom Maclean)

    Especially GUIs is the classic example. Since a long time, you have a really hard time to spot a GUI Api that is NOT modeled with OOP. Even GTK+ (imho the most current and modern GUI implemented with C) is modeled with OOP principles, via glib's GObject.

    It simply doesn't make much sense to implement, extend and/or use a GUI in any other way.

    As everything else, OOP is just a tool, not a joker that fits everywhere. There are lots of areas where it really shines (laserlight's links highlight the strong points of OOP), and others where it just adds unneeded overhead and/or confusion (Carnegie Mellon has already eliminated it from its introductory curriculum the last 2 or 3 years, in favor of imperative & functional programming).

  7. #7
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Hmm... I'm wondering then, would it be possible to write an object-oriented tetrahedral mesh code?

    Basically, I need 4 vertices per tetrahedron. I have a fiducial one which I use to insert extra points. So every time a point is inserted directly into a tetrahedron, it is split into 4 children. And every time one is inserted on the surface there are 3 children.

    Right now, I have function calls that do everything I need them to do. Where would OOP benefit me here? How could OOP optimize my code for me? Would I simply fill my tetrahedrons with functions that I'm already implementing? But now that I think about it, the more it seems to me that keeping all my functions together like that would lead to easier multithreading in the future and improve the understandability of the code.

    Fair enough, I have heard all that I need to. I will now stubbornly re-write my code using an OOP approach in C because it seems more fun that way. Or it could be a giant waste of time, Idrk.

  8. #8
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Mainly because it actually forces us to plan and organize our project long before start coding it.
    O_o

    No.

    "OOP" is just an umbrella term for a lot of different tools.

    Simply having tools and knowing what they are called does not and can not force you to plan and organize.

    You can, easily, patch, pun, or otherwise poorly hack new objects, methods, and such into a poor design; this reactionary pattern is no less or more problematic simply because you are using "OOP". The reactionary part isn't even the problem; indeed, purely reactionary programming is a thing that exists and yields fruit. Simply adding code without considering the design and relationship of components is a part of a inexperienced, lazy, or incompetent programmers life; such behavior is the failure of a programmer and not the tools.

    The requirement to have design documents before coding forces one to plan and organize, but such documents are rarely complete, and often enough, programmers will fall back to simple iterative refinement of design and implementation regardless of such documents. Happily, iterative refinement works regardless of the tools employed.

    Where would OOP benefit me here?
    We can't possibly know the answer to that question.

    Besides, statistically, you are already using "OOP" tools even if you don't know the names.

    Every programmer worth their salt will eventually recreate encapsulation and sub-type polymorphisms even if they are never told about such tools.

    How could OOP optimize my code for me?
    "OOP" will not optimize your code.

    "OOP" can not optimize your code.

    You are responsible for optimizing your code. "OOP" gives you the names of some design and implementation tools. Once you know the names of "OOP" tools, you can find out how to canonically employ the "OOP" tools in your language of choice. Once you know how to implement, or simply use if a given bit of "OOP" is native to a language, you can use "OOP" tools to refactor your design so that it may easily be consumed, maintained, and enhanced by you and others who are familiar with the same tools.

    You can, if you want, think of "OOP" as a specialty of communication where everyone is assumed to know the language. So, for example, we all here know English well enough to communicate so let's go with English literary styles. You might consider "OOP" as a style of poetry like "Blank Verse". "Black Verse" is not the only form of poetry. May of the things that define "Black Verse", such as iambic pentameter, exist in other styles of poetry. By agreeing in advance to use "Black Verse" for communication, we eliminate many of the possibilities of the literary arts which by definition strengthens individual ability to reason about communication thanks to focus and familiarity.

    Giving you tools and the names of those tools is all "OOP" will ever do for you. If you use them poorly, you may see no benefit at all. If you use them too prolifically, you may see no benefit at all. If you use them without regard to canonical implementation, you may see no benefit at all. In other words, "OOP" is no magic bullet; you benefit from "OOP" relative to what effort you put in to using such tools well.

    Would I simply fill my tetrahedrons with functions that I'm already implementing?
    If you do simply and exactly that, you would be wasting your time. You would either already be using "OOP" or start using "OOP" poorly.

    But now that I think about it, the more it seems to me that keeping all my functions together like that would lead to easier multithreading in the future and improve the understandability of the code.
    "OOP" tools don't really address designing for multiple threads, but yes, potentially, if you use "OOP" tools well, you may ease the difficulty of reasoning about your code. Of course, as I've already warned repeatedly, if you use "OOP" poorly, you will probably just make the code worse.

    Soma
    Last edited by phantomotap; 06-06-2013 at 06:32 PM.

  9. #9
    Registered User hex_dump's Avatar
    Join Date
    Dec 2012
    Posts
    88
    Laserlight, that list you wrote down read like episodes of the Big Bang Theory.

    @MutantThe truth of the matter is, even the experts don't agree on what OOP is, and quite frankly even they themselves don't necessarily agree it is necessary. However, it is here and probably will be for some time to come. At it's base Object oriented coding is really just a paradigm, a way to look at code or design your code thus. It took off because it was used heavily in GUI programming for the most part. As a paradigm, it encourages Encapsulation, Inheritance and my personal favorite [a higher level of] abstraction for your code. You can implement your code in C using an oop paradigm, just as you can in C++. The only dif is that the latter makes it a little easier.

    A lot of software places uses it because if done write it can help better organize a large code base. Your mileage may vary with it depeneding on where you work or projects you work on. Just don't think it's the pancea of coding, it's not. I'ts just a programming paradigm. like imperitative, functional etc...learn about it, just don't be myopic about it and you'll be fine.
    Last edited by hex_dump; 06-06-2013 at 06:56 PM. Reason: OP name

  10. #10
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    Quote Originally Posted by MutantJohn View Post
    Hmm... I'm wondering then, would it be possible to write an object-oriented tetrahedral mesh code?
    Anything can be written in an OOP paradigm. Or a procedural paradigm. Or a functional paradigm. Different approaches to programming are not about what can or can't be done, but are rather about different ways to accomplish the same goal. Depending on your goal, one or the other might be more elegant, or more maintainable, or more clearly understood, or less prone to error, but all of the approaches are possible.
    You ever try a pink golf ball, Wally? Why, the wind shear on a pink ball alone can take the head clean off a 90 pound midget at 300 yards.

  11. #11
    Registered User
    Join Date
    May 2012
    Posts
    505
    Quote Originally Posted by MutantJohn View Post
    Malcolm, would you be willing to elaborate what you said about geometric shapes and big integers?

    Also, I have seen an object as a solution to certain if-statements. Expanding upon what you said, all those mechanical devices brake but they do it differently. So instead of checking the type of structure with an if, you could just call the brake function in the object.
    Most C compiler will allow you to work with integers up to 32 or 64 bits. That's enough to count practically anything. But it's not enough for some calculations, e.g. the total number of games of bridge that can be played (roughly 52!, but the no revoke rule will cut it down a bit).
    So you can define a big integer object, in C++ with operator members functions. Then you just do your calculations with it, in the normal way.

    The same goes for geometrical shapes. Say we want to cut a bit out of an image. We could cut a square, a circle, a trapezoid, a triangle, an octogon, anything that consisits of a closed shape defined by lines.
    So we define a "shape" object, then derive all the specific shapes from it. Then we pass the shape to the cut_image function. It will probably return the bounding box, with pixels outside the shape set to alpha of zero.

    We don't need a big if or switch. The code could could simply call "getMaxX" type functions to find the bounding box, and pointInShape functions to pick each pixel. These would be overloaded for each shape.
    I'm the author of MiniBasic: How to write a script interpreter and Basic Algorithms
    Visit my website for lots of associated C programming resources.
    https://github.com/MalcolmMcLean


  12. #12
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    The same goes for geometrical shapes. Say we want to cut a bit out of an image. We could cut a square, a circle, a trapezoid, a triangle, an octogon, anything that consisits of a closed shape defined by lines.
    O_o

    A continuous lists of cubic Bézier spine control points do the same thing far more generally exhibiting more power without needing to build a bunch of different classes.

    The stream example was a much better example.

    Soma

  13. #13
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Lol I'm never gonna code a GUI. Ty, guys. You talked me off a ledge, here. I don't know nothin' 'bout no paradigms, I just code what needs to be done and I'ma done code it well.

  14. #14
    Registered User
    Join Date
    May 2012
    Posts
    505
    Quote Originally Posted by phantomotap View Post
    O_o

    A continuous lists of cubic Bézier spine control points do the same thing far more generally exhibiting more power without needing to build a bunch of different classes.

    The stream example was a much better example.

    Soma
    That puts a burden on the programmer.

    Anyone can define a triangle, octogon, circle, pie wedge, etc using simple code. If all these things have to be specified by lists of Beziers it's much harder to program, unless you really know what you're doing. Also Beziers are rather difficult for artists to enter and control in GUIs.

    Remember we're cutting a shape out of an image. 90% of that time that will probably be an axis-aligned bounding box.
    I'm the author of MiniBasic: How to write a script interpreter and Basic Algorithms
    Visit my website for lots of associated C programming resources.
    https://github.com/MalcolmMcLean


  15. #15
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    That puts a burden on the programmer.
    O_o

    (I'm reading that as "client" because a programmer would be responsible in any event.)

    No. It does not.

    *shrug*

    In fact, you almost certainly knew that statement was wrong when you wrote it.

    You are obviously limiting your imagination in a "knee jerk" reaction to my suggesting that the "image cutting with shapes" example is a poor case for inheritance based polymorphisms.

    Anyone can define a triangle, octogon, circle, pie wedge, etc using simple code.
    What makes you think the solution has to be classes to yield "Anyone can define a new shape using simple code."?

    Using a simple interface to build a complex object with a familiar utility interface is easier than building a complex object which must provide a simple interface without such a familiar utility interface to rely upon when your algorithms understand the complexity by repeated application of the simple objects. Granted, this holds true for classes just as much without classes; the only difference being the "where" of the implementation code as surely the underlying primitives and algorithm must still be provided, but certainly, you don't need inheritance based polymorphisms even if you chose classes as an implementation strategy.

    If all these things have to be specified by lists of Beziers it's much harder to program, unless you really know what you're doing.
    Well, that is obviously true, but also obviously an aspect of simply being far more generic and cubic Bézier splines being more complex shapes.

    If you, later, worry about performance, you could also provide pixel, triangle and ellipsoid based data polymorphisms which, between the three, covers everything that can be drawn with very good communicability (fewer bytes used to build a shape) and algorithm performance (less complexity to process an image from data that is known to represent a series of triangles instead of triangles built from cubic Bézier splines).

    Also Beziers are rather difficult for artists to enter and control in GUIs.
    You've never actually used a vector drawing program have you?

    Even primitive vector drawing tools have a simple "drag control points around the canvas" approach which could not possibly be simpler to use.

    Enjoy: SVG Cubic Bézier Curve Example

    "Adobe Illustrator" has an epic level pen tool with "convert to path" and "path to Bézier curve" options which could not simpler or really, I think, more powerful.

    Of course, getting them from drawing program to your code isn't seamless, but thanks to "SVG" is very "doable".

    Also, for shapes which can be based on triangles, the Bézier curves would be fixed, strait lines greatly simplifying the ease of implementing such complexity over lines and ultimately over Bézier curves. In other words, using existing shapes to create new shapes, but of course, this applies to inheritance based polymorphisms if you do the job well.

    Remember we're cutting a shape out of an image. 90% of that time that will probably be an axis-aligned bounding box.
    You seem to be under the impression I suggested that one shouldn't have convenient utilities.

    I said nothing of the sort. I'm only suggesting that one needs no class hierarchy to do the exact same job with the same convenience, utility, and mechanism the class hierarchy would accomplish with a very similar interface making the example a poor choice for showing where inheritance polymorphisms shine.

    The first example block is using inheritance based polymorphisms to do the job of "cutting a shaped image from an image".

    The second example block is using data based polymorphisms to do the job of "cutting a shaped image from an image".

    As you see from the example, the convenience of complex shapes is available to a client regardless; in fact, I would consider that issue, more available tools which are simple to use, a "quality of implementation" issue being completely unrelated to the method of interface.

    Here, I consider the use of templates to be poor just as much as the inheritance based solution; I'm only using invoking the standard container for the sake of simplicity as the examples are already bloated for such a simple discussion.

    Soma

    Code:
    // Implementation
    typedef /**/ SColor;
    // ...
    class SScanline
    {
        // ...
        SColor getPixel
        (
            size_t fOffset
        );
        // ...
    };
    // ...
    class IImage
    {
        // ...
        SScanline getScanline
        (
            size_t fOffset
        );
        // ...
    };
    // ...
    class IShape
    {
        // ...
        virtual IImage * cut
        (
            IImage * fImage
        );
        // ...
    };
    // ...
    class STriangle:
        public IShape
    {
        // ...
        virtual IImage * cut
        (
            IImage * fImage
        )
        {
            // Use `getScanline' and `getPixel' to obtain pixel within the target zone.
        }
        // ...
    };
    // Client
    void Go() // This is not meaningfully different.
    {
        IShape * sShape(new STriangle(/*position, rotation, scale, whatever*/));
        IImage * sImage(new PNGImage("filename.png"));
        IImage * sResult(sShape->cut(sImage));
    }
    Code:
    // Implementation
    // data polymorphisms communicating "béziergon":
    // double gShape[] =
    // {    
    //      begin_x, begin_y // start of spline and curve 1 {P0}
    //    , ctr1_1_x, ctr1_1_y // curve 1 control point 1 {P1}
    //    , ctr1_2_x, ctr1_2_y // curve 1 control point 2 {P2}
    //    , /* ... */, /* ... */ 
    //    , nxtN_x, nxtN_y // end of curve N closing to (begin_x, begin_y) {P3/PN}
    //    , ctrN_1_x, ctrN_2_y // curve N control point 1 closing to (begin_x, begin_y) {PN+1}
    //    , ctrN_1_x, ctrN_2_y // curve N control point 2 closing to (begin_x, begin_y) {PN+1}
    // };
    std::vector<double> CraftSquare(/*position, rotation, scale, whatever*/)
    {
        std::vector<double> sResult(12);
        // fill with {P0,P1,P2,P3, /**/, P12}
        return(sResult);
    }
    // ...
    grid<color> CutImage
    (
        grid<color> & fSource
      , std::vector<double> & fBeziergon
    )
    {
        grid<color> sResult;
        // Use grid to obtain pixel within the target zone.
        return(sResult);
    }
    // Client
    void Go() // This is not meaningfully different.
    {
        std::vector<double> sShape(CraftSquare(/*position, rotation, scale, whatever*/));
        grid<color> sImage(PNGImage("filename.png"));
        grid<color> sResult(CutImage(sImage, sShape));
    }
    Last edited by phantomotap; 06-08-2013 at 11:08 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Encapsulation and objects within objects
    By nair in forum C++ Programming
    Replies: 4
    Last Post: 07-31-2011, 10:42 AM
  2. Replies: 1
    Last Post: 05-24-2011, 06:36 PM
  3. Objects as attributes of other objects.
    By kbro3 in forum C++ Programming
    Replies: 10
    Last Post: 08-15-2009, 03:46 PM
  4. Assigning objects to objects
    By Swordsalot in forum C++ Programming
    Replies: 4
    Last Post: 07-26-2006, 03:47 AM
  5. Replies: 4
    Last Post: 10-16-2003, 11:26 AM