Archived

This topic is now archived and is closed to further replies.

Classes -- what's the point?

This topic is 5824 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have always wondered what the point of using Classes was. I can''t see how they are any better than using Structs and functions outside of a class. Are there any benefits of using Classes? The reason I''m asking is because I want to make a particle effects engine (I''ve made one before, but I''m bored and want to make a better one ). I am planning on using a struct and a linked list to keep track of all the data, but if using a class was somehow more efficient, then I want to use that instead.

Share this post


Link to post
Share on other sites
At first look it''s just another way to ''tidy up'' your code, but if you want to restrict access to certain variables to only a few functions, you can do this with class. They can turn out to be very useful.

-J

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
A class is obvious less efficient because theres one more step although theres hardly any difference. Destroy(&Thing); is IMO no better than Thing.Destroy();. So if you look at it that way then classes are no better than structs and external functions. But classes do have inheritence (yes i know the struct keyword can do that but) which can be useful for things like particle engines. Theres so little speed difference and there is the advanatage of inheritence so i recoment classes for your particle engine. Anyway, if you know how to make a particle engine wouldnt you already know the answer to this question?

Share this post


Link to post
Share on other sites
The one thing that bothers me about classes is how they are often delegated to one-shot tasks. For example, say there''s a class called "CMyDirectX" which will be used to encapsulate DX functionality in a project. If it''s only used once in a single object... I really don''t see the point of writing a class that will only be instantiated once.

I think classes are overrated. I dunno, maybe that''s just me.

Share this post


Link to post
Share on other sites
Ok, here''s an example of a good use of classes ...
Suppose you are writing a 3d engine, and you want to support multiple graphics APIs. You can create a CRenderer class, and a number of derived classes, such as COpenGLRenderer, CD3DRenderer, and CSoftwareRenderer. You can now change which renderer your engine uses simply by creating an object of a different type. No other code in your app has to change.

  
CRenderer* pRenderer;
if(CApp.menuSelection == R_OPENGL)
pRenderer = new COpenGLRenderer;
else if(CApp.menuSelection == R_DIRECT3D)
pRenderer = new CD3DRenderer;
else if(CApp.menuSelection == R_SOFTWARE)
pRenderer = new CSoftwareRenderer;

pRenderer->transform();
pRenderer->calculateVisibility();
pRenderer->drawScene();
pRenderer->flip();

Or something like that. It''s a lot easier to do with classes than with structs and function pointers.

Share this post


Link to post
Share on other sites
quote:
Original post by Oluseyi
But in several projects. It''s called "code reuse."

I think he was refering to that as oppossed to functions (maybe not?). What immediately came to mind for me is the "random number" class that I''ve seen before. I think it''s pretty pointless to have a class for random numbers when you could just have a couple functions in a "RandGen" namespace or something.

[Resist Windows XP''s Invasive Production Activation Technology!]

Share this post


Link to post
Share on other sites
As with all things, OOP is not a panacea. You still have to make intelligent design decisions when utilizing classes/structs and methods/functions. Sometimes I prefer to use file-scope OO, or namespaces. So rather than having a CGraphicsContext class with an Initialize method and so on, I might simply have InitializeGraphics() with static data at filescope.

In other (and much fewer) words, I agree entirely.

[ GDNet Start Here | GDNet FAQ | MS RTFM | STL | Google ]
Thanks to Kylotan for the idea!

Share this post


Link to post
Share on other sites
I think it''s much clearer to write a common interface-header, like:

video.h

and then do the implementations in different cpp-modules, like:

video_win.cpp
video_linux.cpp

with global "member variables", rather than making a interface-class and inheriting video-classes for all platforms...

BTW: My 1st post, yay!

Share this post


Link to post
Share on other sites
Let's say you want functions to draw tiled maps and sprites. You could call your functions "DrawMap" and "DrawSprite", although that can get annoying (I've been there). You could overload them: "Draw(MAP *map)" and "Draw(SPRITE *sprite)", but then, when you're reading this...

Draw(MainMap);
Draw(Player);
for(int n = 0; n < NumObjects; n++)
    Draw(Objects[n]);

...you still have to look at what's inside the brackets before you know what's being drawn. If you use classes, you'd be looking at this...

MainMap->Draw();
Player->Draw();
for(int n = 0; n < NumObjects; n++)
    Objects[n]->Draw();

...and since we are used to reading from left to right, this generally helps. We already know we're looking at the drawing code, so we should put the object on the left, where we will see it before "Draw". Reading "Draw" won't help you.

Also, c++ has operator overloading...

EDIT: I think I'll try [n] instead of [ i ]

Edited by - Beer Hunter on December 31, 2001 6:23:29 PM

Share this post


Link to post
Share on other sites
After seeing C code that was doing its best to be class-like, I truly appreciate the benefit of classes. But often you don''t need the power of classes when a struct will do.

If you find yourself doing a lot of switch-case or if-else then consider classes. Also, constructors and destructors for classes can be quite handy. Then there''s the virtual functions.

If you want 10 different types of effects in your linked list, you can use the exact same function call on all of them as you loop through, casting their pointers to the base class type.

Classes aren''t necessarily more efficient performance-wise though.

Share this post


Link to post
Share on other sites
quote:
Original post by Anonymous Poster
A class is obvious less efficient because theres one more step although theres hardly any difference.

Without virtual inheritance, there are zero more steps.

I don''t know if it''s mandated by the C++ standard, but the behaviour of compilers with class methods is this:

The method is just a regular function. The only reason that it''s a method rather than a regular function is that its first parameter is always a pointer to a class.

When you invoke the method:
  MyClass.myMethod(1, 2, "Hello");  

the code generated is typically something like
  myMethod(&MyClass, 1, 2, "Hello");  

The actual class (the thing pointed at) merely stores the state information (that is, the member variables).

The benefits here are the checks the compiler can do for you.

IMO it is a little clearer to not have to pass pointers to some state-storing struct around -- that is, I prefer MyClass.myMethod() to method(&MyClass).

But more importantly, there are various checks that can occur at the C++ level. For instance, you can control the accessibility of methods. With the struct style, you can''t declare a function that takes a pointer to a struct such that it can only be called from a different function taking a pointer to the same kind of struct. In C++, you can; a protected or private method has this constraint.

This is useful even for one-off bits of code -- it is generally useful to differentiate between those bits of code that you use to manipulate the state information (public methods) and those bits of code that are used to effect changes but whose use is irrelevent to the task at hand (for instance, if you have a linked list class, whilst it might be made up of nodes and have node manipulation routines, when using the class you shouldn''t ever be concerned with such matters; you''re not interested in how it works or anything like that).

With virtual function calls, there is an additional pointer dereference required to call the function, as well as a small memory overhead to store the v-table. In these cases, the classes do incur a (very slight) performance overhead. However:
(1) The overhead is only there when you choose to use it (C++ doesn''t make functions virtual by default)
(2) If you need such functionality, you''d have to work pretty hard to mimic it with structs and external functions
(3) And if you did mimic it, you''d incur the same kind of performance penalty as C++ incurs anyway.

quote:
Destroy(&Thing); is IMO no better than Thing.Destroy();. So if you look at it that way then classes are no better than structs and external functions. But classes do have inheritence (yes i know the struct keyword can do that but) which can be useful for things like particle engines.

In C++, structs are identical to classes, except structs default to public access, classes default to private. I think the assumption is made that when talking about structs one means old C-style POD structs, with no c-tor/d-tor, no member functions, no access control, no inheritance.

I prefer classes over structs and external functions. Even if not using inheritance and such, the access control and the cleaner interface makes them worthwhile. It''s also easier for my IDE; it can list the methods that belong to an object whereas it can''t list the external functions that take a pointer to a particular kind of struct as their first parameter.

Share this post


Link to post
Share on other sites
classes are designed to support "object orientation". although im not aware of any pure oop languages, oop is basicly a strategy that forces association between code, variables, constants, and other objects, through structures like classes.

if you use a class, your forcing associations between things.

in c++, the struct and class keywords are transparent (?).

its good practice to figure out how to make your code object oriented, by using classes - it will be more organized, readible, modular, and maybe more effecient.

Share this post


Link to post
Share on other sites
quote:
Original post by Anonymous Poster
A class is obvious less efficient because theres one more step although theres hardly any difference. Destroy(&Thing); is IMO no better than Thing.Destroy();. So if you look at it that way then classes are no better than structs and external functions. But classes do have inheritence (yes i know the struct keyword can do that but) which can be useful for things like particle engines. Theres so little speed difference and there is the advanatage of inheritence so i recoment classes for your particle engine. Anyway, if you know how to make a particle engine wouldnt you already know the answer to this question?


Great. Now what happens when you have 9 or 10 different structures?

Destroy(&Thing);
Trash(&ADifferentThing);
Scrap(&Thingamabob);
Discomblomerate(&Doohicky);

Pretty soon you''re going to run out of meaningfull terms. It sounds to me like you''re just newbies who read about classes and think that that''s all that OOP/OOD is about. Here''s a clue, go read up on polymorphism.

Share this post


Link to post
Share on other sites
Object-Oriented-Programming is awesome!
quote:
It sounds to me like you're just newbies who read about classes and think that that's all that OOP/OOD is about. Here's a clue, go read up on polymorphism.

Couldn't have said it any better myself. Classes bring in expandability to themselves, which is the only reason that C++ supports structs. Structs are just there for compatibility, so that classes are 'free to expand'. Classes come with:

1. Constructers/Destructors - You better have at least constructers when dealing with objects.

2. Polymorphism - Could somebody say 'virtual'? Polymorphism is awesome, especially if you're making something that is (new term to C programmers)inherited (say it with me now).

3. Inheritance - As the other people explained above

4. Operator Overloading - This, although known for making code extremely hard to understand, but if used properly, they can make code so much more useful.
    
// Sorry, this matrix stuff I don't know a whole

// bunch about, but it's the best example I can

// think of.

class CMATRIX
{
public:
// overloaded constructor

CMATRIX (float fUx,float fUy,float fUz,float fUw, // model-space x

float fVx,float fVy,float fVz,float fVw, // model-space y

float fWx,float fWy,float fWz,float fWw, // model-space z

float fTx,float fTy,float fTz,float fTw); // world-space position


CMATRIX operator*(CMATRIX mat); // operator overloading

private:
float ux, uy, uz, uw, // declare all the variables

vx, vy, vz, vw,
wx, wy, wz, ww,
tx, ty, tz, tw;
}
CMATRIX::CMATRIX(...) // scope resolution operator

{
ux = fUx; // initialize all the variables

uy = fUy;
uz = fUz;
uw = fUw;
vx = fVx;
vy = fVy;
vz = fVz;
vw = fVw;
wx = fWx;
wy = fWy;
wz = fWz;
ww = fWw;
tx = fTx;
ty = fTy;
tz = fTz;
tw = fTw;
}

CMATRIX CMATRIX::operator*(CMATRIX mat)
{
CMATRIX temp; // temporary matrix

mat.ux mat.ux * temp.ux;
mat.uy mat.uy * temp.uy;
// and so on...

return temp;
}

int main()
{
CMATRIX mat1(...);
CMATRIX mat2(...);

mat1 = mat1 * mat2; // multiply the two

return 0;
}

Long, huh. The '...' is really just cause I was board, not cause of the %d's and stuff. The code is pretty buggy, and I don't know operator overloading that well, so it may be weird to you. It's probably really wrong, especially since i don't know jack about matrices. Well, there are a lot more, with the next one on my list friends, also, if used by the right programmer, can go a long way.

'Whoever said, "It's not whether you win or lose that counts," probably lost.' -Martina Navratilova

Edited by - tuxx on December 31, 2001 12:21:45 AM

Share this post


Link to post
Share on other sites
I never said I disagreed with object orientation in general, I merely disagree with certain uses for classes. The very name implies it should be used for generalization of abstract structures. Writing a whole class that will be realized in one and only one object in the entire program seems like a lesson in contradiction. The class is in a class by itself. How ironic/oxymoronic.

It''s like designing an entirely new automobile and producing a single product on the assembly line.

Are classes good? Oh yes, but like the weekend handyman who drives a nail with the handle of a screwdriver, it all comes down to using the right tool. If I''m writing a specific subsystem for my program, like the OpenGL wrapper to handle the graphics, I''ll use (global) functions and structs and variables. If I''m going to be writing routines to handle objects in a game world where each object can be thought of as being classifed (hint hint) in the same general group and where specialized sub-types lend themselves beautifully to inheritance, then I''ll definitely write a family of classes.

And oh yeah, happy new year.

Share this post


Link to post
Share on other sites
It''s all about using the right tool for the job.

Go visit your local woodworker, auto mechanic, dentist, or just about any other skilled worker. You will notice that each has many tools at their disposal. C''mon do you really want your dentist using a drill that''s any larger than absolutely necessary?

So too the computer programmer has various tools. Ignoring things likes development tools for a second, i''m talking about languages. Most people will accept that VB, JAVA, C++, and even COBOL have their time and places for use (although some would argue with my assessment of COBOL ).

Now here''s the hard pill to swallow. C and C++ are different tools. Sure your C programs should compile under C++, and yes C++ is based on C. The key is they were developed for different reasons.

C was developed to be, in the eyes of K&R "a programmer''s language". Meaning, among other things, that it has the ability to perform all the tasks a "programmer" would want. This is in contrast to scripting languages which are much easier to learn and use, but far more restricted in their flexibility. Hard core programmers don''t like restrictions.

C was developed at a time when computers and computing resources were very limited. Compiled code needed to be small, fast, and flexible. Therefore, it is no surprise that in the right hands C code can do all that and alot more.

C++, however, was developed for different reasons. Stroustrup pointed out that part of the reason he based C++ on C (rather than starting from scratch) was to help the thousands of C programmers (and all of their existing code) make the move to a more modern language.

One of the driving forces behind Stroustrup''s development of "C with classes" was to take advantages of modern computer hardware. Hardware was (and still is) becomming cheaper and faster, thus programmers were less constrained by the available computer resources.

This, of course, has the effect of giving programmers the ability to write larger (read: more complex) programs. The downside to the larger programs is that C was ill-equipped to deal with very large programs.

Why was it ill-equipped? Two reasons: old C-style structs (as pointed out by another poster) did not have all the functionality of todays C++ classes. Second, C used procedural-style programming methodology. Brute force programming is more like it.

C++, on the otherhand, was developed with a completely different programming methodology: OOP (that''s Object Oriented Programming in case i''m getting carried away with my acronyms here).

Stroustrup pointed out that for "smaller" programs (he defined smaller programs to be ones with fewer than 10,000 lines of code i believe), C-style "brute force" progamming works fine.

The point (yes i''m trying to answer your question!) is that C++ was designed to facilitate larger programs to be written. Thus, it''s a different tool than C and has it''s own pro and cons as well. Thus, it has its "right" time for use. Of course, OOP itself brings it''s own problems to the table. Namely larger source code, larger .exes and slower executing code than an equivalently coded C program.

I know half of you are going to complain about that last sentence, but think of it in these terms. Pretend for a moment you have two identically performing programs, on written in C and the other in C++. You write the C version using procedural methods (globals, inlined, the works), and your C++ is total OOP. Total data hiding, accessor methods, C-tors, D-tors, et cetra.

The C++ will still run fast, but with all the construction, destruction, function calls it *will* without a doubt have substantially more overhead than the comparable C code.

The bottom line: Yes, you can make a C program C++ "like" and visa versa. Remember, though, that each was written with different programming methodologies in mind. If you want to write an OS (a good OS, not windows) make it fast, lean, efficient and use C/brute force. On the otherhand if you are trying to write a million-line program, save yourself about a million headaches and use C++/OOP. It will be slower, but at least it will work right. In the end a slightly slower executing program that works flawlessly is worth infinitely more than a faster one that doesn''t work right at all.

that''s my 1/50th of a dollar
~don

P.S. i''m a bit tired so please forgive the spelling and grammar errors.



"They that can give up essential liberty to obtain temporary safety deserve neither liberty nor safety."
- Benjamin Franklin

Share this post


Link to post
Share on other sites
Give this man a beer for one hell of a well written post that was long and wasnt tiring to read!

-----------------------
0wn 0wn 0wn your goat
gently down the pw33n

Share this post


Link to post
Share on other sites
>> On the otherhand if you are trying to write a million-line program, save yourself about a million headaches and use C++/OOP. It will be slower, but at least it will work right. >>

It should be noted that this statement is based on the assumption that you can design your large applications equally well with or without clever design methodologies such as OOP and with or without language support for such methodologies. In practice, high-level conceptual design decisions often have a much greater effect on the overall performance of large applications than any low-level code optimizations that might be achieved by using some lower-level language such as C instead of C++.

Henry

Share this post


Link to post
Share on other sites
Henry:

C is at a lower level than C++?

Basically, C is procedural and C++ is procedural plus modular, object-oriented, and generic. Given that C++ supports C''s procedural concepts (pointers, functions, data structures, bit manipulation, and "unsafe" type-casting) and their functionality, how can it be said that C is a lower-level language than C++?

Share this post


Link to post
Share on other sites
quote:
Original post by Omaha
I never said I disagreed with object orientation in general, I merely disagree with certain uses for classes. The very name implies it should be used for generalization of abstract structures. Writing a whole class that will be realized in one and only one object in the entire program seems like a lesson in contradiction. The class is in a class by itself. How ironic/oxymoronic.

It''s like designing an entirely new automobile and producing a single product on the assembly line.



Ah, but how can you know with 100% certainty that you won''t be requiring more than one instance in the future? Or that you or someone else might not need to derive a new class to add functionality? Making it a class in the beginning can save time and headaches in the future.

quote:
Original post by Omaha
If I''m writing a specific subsystem for my program, like the OpenGL wrapper to handle the graphics, I''ll use (global) functions and structs and variables.



IMO, that''s the perfect time to use classes. Create an abstract general graphics class and then you can derive an OpenGL, DirectX, etc, class for each API. Then your program can use any graphics API and even switch between them in game by just adding a line or two of code.

I''m not saying one should use classes all the time, but rather that I think they are useful in more cases than you think, IMO.

On the other hand, the STL is also a good example of how functions can be used to enhance generic classes and improve reuseability.


- Houdini

Share this post


Link to post
Share on other sites
quote:
Original post by Anonymous Poster
to Beer Hunter:

reading Draw first is easier.



Maybe my explanation wasn''t clear enough, so I''ll go through this slowly and logically...

Assumptions:

a) The program is written with good coding style.
b) Your first language was English, or some other language that teaches you to read from left to right.
c) Reading the same thing repeatedly without good reason is a waste of time.
d) The word "Draw" must appear somewhere on the line.

Therefore:

1) From (a), when you are looking at the drawing code, you will know that you are looking at the drawing code.
2) From (a), the drawing code is uninterrupted by other actions.
3) From (c), (1) and (2), Reading "Draw Draw Draw Draw" is a waste of time.
4) From (3), the last thing you want to read is "Draw".
5) From (b), (d) and (4), "Draw" should be as far to the right as possible.
6) From (5), we can conclude that "Map->Draw()" is better.


Maybe you only prefer "Draw(Map)" because you''ve been using it for too long, and you''re just so used to it that you don''t want to change over. That''s fine, but it''s not a valid argument as to why it''s naturally superior.


/me receives an award for the longest reply to a 5 word statement.

Share this post


Link to post
Share on other sites
quote:
Original post by Maximus
Give this man a beer for one hell of a well written post that was long and wasnt tiring to read!



thx Maximus
I''ll take a Corona pls.


~don

"They that can give up essential liberty to obtain temporary safety deserve neither liberty nor safety."
- Benjamin Franklin

Share this post


Link to post
Share on other sites