Skip to main content
gamedev.net
🔒 Locked

Modular classes article sucks

Started by ryoder 17 replies 1k views
Original Post
ryoder
ryoder
That was the stupidest article I ever read on programming. I thought he would give us a new way to make inheritance and encapsulation work without C++''s implementation but instead he wrote a really dumb article that uses arrays of values which are not even logically tied together to "simulate" inheritance. Now that I have made my negative comments here is how I would write C++ features in a C only language, and I''ll finally address why its a total waste of time. I''ll write a class called Pixel which will hold x, y and color values with some restrictions on range. x -> 0-639 y -> 0-379 c -> 0-255 By routing access to internal properties of a class through accessor methods, the programmer can be assured of the range of values held by a pixel so that whenever a pixel is plotted it is always within a certain constraint. Further using an accessor method allows other "events" to be kicked off. Here is the C++ way class Pixel { public SetX(int newVal) { if(newVal >=0 && newVal <=639) m_X = newVal; } public SetY(int newVal) { if(newVal >=0 && newVal <=379) m_Y = newVal; } public SetColor(int newVal) { if(newVal >= 0 && newVal <= 255) m_Color = newVal; } protected: int m_X; int m_Y; int m_Color; } This class is easy to use and provides protection against stray values. Additionally the hardcoded limits could be changed or a lookup table could be used for different resolutions. If you wanted to subClass pixel you could override only specific methods to provide additional processing, like a dynamic pixel who redraws itself every time its properties are changed. Obviously using a whole class for a pixel is probably a waste but this is just an example. THE OLD WAY:: typedef struct { int x, y, color; } POINT; POINT_SetX(POINT * p, int newVal) { if(newVal >= 0 && newVal <= 639) p->x = newVal; } This is the old way and this sucks because all methods that operate on type POINT usually take the POINT_ prefix and you always have to pass a pointer to the object and if you don''t want to use the SetX method you don''t have to so some idiot could set the value of X to something out of range and unknown problems could occur. I used to program this way. I would have a struct for basic sprites and enemy sprites like a flying saucer would have a pointer to the basic sprite inside them so they would inherit methods (kind of) but I found myself writing so many MoveEnemy(Enemy * e) methods and KillEnemy(Enemy * e) etc that my code was hard to read. THE ALTERNATIVE::: The alternative to using C++''s built-in class keyword to define objects is to use structs with pointers to methods. This is a big pain in the ass and its impossible to have private and protected struct members. THE CONCLUSION:: Just learn oop and C++''s way of doing it and use it. Don''t abuse it and it will make your code much cleaner and easier for others to use, read and extend. MCSE, MCSD, Sun Certified Java Programmer Pimp Daddy ;)
MCSE, MCSD, Sun Certified Java ProgrammerPimp Daddy ;)
ImmaGNUman
ImmaGNUman
Ok, shut up. No advertizing C++. If you want to use it, do so, if you don''t, then don''t. I am tired of hearing from people who are incredibly cocky and think their language is the best. Please try your best to realize that there are a few who do not use a OOP langauge.

-----------------------------

A wise man once said "A person with half a clue is more dangerous than a person with or without one."
-----------------------------A wise man once said "A person with half a clue is more dangerous than a person with or without one."The Micro$haft BSOD T-Shirt
tcs
tcs
ImmaGNUman, I really don't think it's fair what you say. ryoder just said his opinion about the approach, and he is damn right. I read the article and can't find the point of it. I really don't see why anyone should put stuff in global arrays vars... and then stating it's a C approach to OOP ??? C is like don't using the mouse in Quake: You'll suck compared to other that do. The only argument that may be taken as valid is that C is more optimized than C++, but who cares ? The age of procedurals programming was a decade ago, now we are taking the step from source level components (classes) to binary level components (COM, ...). Why bothering with procedural programming, and especially why bothering with an unintersting approach to procedural programming ?

Maybe the next part of the series has some useful informations ?
Maybe we all misunderstood the point of it, dunno...

Tim

--------------------------
www.gamedev.net/hosted/glvelocity
glvelocity.gamedev.net
www.glvelocity.com

Edited by - tcs on June 26, 2000 8:01:05 PM
Tim--------------------------glvelocity.gamedev.netwww.gamedev.net/hosted/glvelocity
Dogfood
Dogfood

I think it should be noted that there is _more_ than one way to accomplish OO aspects in a non-OO language, especially C. I also have you know that this is not totally useless. Here is a specific applications: platforms(especially embedded systems) where a C++ compiler is not available.



Something that I do which was not really mentioned in the article is a case of single inheiritance. Example:

typedef struct baseclass {

int x;

int y;

} BASECLASS;


Derived class:

typedef struct newclass {

BASECLASS parent;

int z;

} NEWCLASS;



Now here is where it has power: A pointer to newclass can be typecast to a pointer to baseclass without ANY issues. The compiler formats the beginning of NEWCLASS structure the same way it formatted BASECLASS in memory, therefore any code that uses BASECLASS can work with NEWCLASS(unless you modify the behaviour, but the whole idea is NOT to do so).



About the global table of instances of objects: it was a neat idea, I always make a pointer to the "object" an additional argument to the function thus avoiding all issues his technique creates. Actually I believe C++ implements it closer to my way, it passes an additonal hidden argument in functions which is a pointer to the instance of the class being called.



Someone mentioned COM. Well, technically a COM interface is array of pointers to functions. Needless to say, C function pointers have a great deal of power, and it would be possible to use this as well, here''s an example.



About three years ago, I was working on my 3d engine, when software rendering was still an option, and Glide was still a pretty good choice. I used a set of function pointers to a base triangle drawing function. This pointer was set at the initialization to either the software rasterizer, or glide rasterizer. Anytime a triangle needed drawing, this pointer was used, eliminating the need for a test everytime to determine the triangle drawing routine. Another case: I wrote a parser for HTML, and decided that I would have a general tag processing function, so I made a hash table of pointers to functions, hashed by tag name, and then as I parsed the file, I simply looked up the tag name in the table and called the function I found. When I need to add a new tag, I just add a call to add it to the table in the parser initialization, and then write the functions.



Of course, if I wanted to use a OO language, I could, but there is also another benefit to using a language like C: experimenting with techniques for OO stuff NOT available in your language. Guess what, your OO language is not completely OO, nor is it the only approach to OO, but because it has certain attitudes and decisions in its approach your limited by that. I my procedural language I can write OO code unencumbered by the decisions of the designers of C++ or Java, and can experiment with techniques that you may find in your NEXT OO language.



I didn''t mean that as a rant, but I just wanted to point out something other than what he talked about, and techniques I find useful. Hey, here''s a PRODUCTIVE idea, lets turn this thread into a discussion of techniques rather than flamebait and making fun of the guy who wrote the article.

ryoder
ryoder
That was the purpose of my original post.
I was very interested in reading the article at first.
Being able to create an easily usable inheritance model with encapsulation without using built-in C++ stuff would be great in some cases.

But the article just had arrays of members that are statically allocated and this is just plain wasteful.

I agree with the guy who has a struct with a pointer to the base struct. Thats what I did before I learned C++.

My whole point was that I was creating some of the basic C++ oop technology with structs and function pointers and when I realized how easy C++ is and that it allows more typechecking and is easier to read I just decided to use it.

It makes your skills more marketable to companies using these technologies too. Why learn something or create something that no one ever uses?

The way I use OOP is to define large classes which expose limited functionality like sprite classes with simple methods like stepAnimation() setAnimation(int animIndex) and render() or load(char *fileName) and subClass from there once or maybe twice but no further.

Some people use objects for everything and that is wasteful. For example have a C3DObject class with an array of pointers to VertexBuffers instead of using template classes. Its faster.


MCSE, MCSD, Sun Certified Java Programmer
Pimp Daddy ;)
MCSE, MCSD, Sun Certified Java ProgrammerPimp Daddy ;)
The_Senshi
The_Senshi
Since this sounds like it''s becoming a C vs. C++ vs Other languages flame war, I shall give the following advice to those of you who even feel this is arguable:

Learn a new language every year

If you stick to just one language your limiting your problem solving skills.

Like the saying goes: "if your only tool is a hammer, every problem is a nail".
----------------------------------"Death has come to your tea cup."
Ysaneya
Ysaneya
> C is like don''t using the mouse in Quake: You''ll suck compared to other that do.

Isn''t Quake III all written in C ( with few parts of ASM ) ? Are you saying Quake III technically sucks ?

I always thought there is no ultimate language. Some are better than others for specific applications, but they''re all tools. You can make good code in C and bad code in C++, or the opposite. None is better. They''re simply *different*, and that''s my point. If you want to do OOP, you''ll sure prefer C over C++, but nobody wants to use OOP nowadays.

Y.
The_Senshi
The_Senshi
quote:

If you want to do OOP, you''ll sure prefer C over C++, but nobody wants to use OOP nowadays.



I think you confusing OOP with procedural programming.

OOP == Object oriented programming, which is why one would use C++ over C. Not the other way around.

So what you probably meant was this:

"If you want to use procedural programming, you''ll sure prefer C over C++, but nobody wants to use procedural programming nowadays."

Of course, I disagree with that last segment. I use OOP quite often, but for small tools procedure programming is usefull.



----------------------------------
"Death has come to your tea cup."
----------------------------------"Death has come to your tea cup."
Mezz
Mezz
Ryoder, there were probably more stupid articles on programming, but that isn''t the point...

Yes, I agree that some of the methods outlined in the article could be described as clumsy, and that to an C++ OOP programmer would seem ugly and disfunctional, but that isn''t what the author set out to do was it? - he/she set out to show a way in which modular programming could be achieved without the use of classes. The author achieved at least part of this goal, it may not have been the best way, it may not have been what some people were looking for, but at least the guy tried, and I cannot fault them for that.

-Mez
Gladiator
Gladiator
And that was Part I out of (how many?)... there''s more to come...
Myopic Rhino
Myopic Rhino
I''m not sure that there will be more. I haven''t heard from the author in a couple of months. And based on the response to the first one, it''s unlikely that we''ll post the rest.
Gladiator
Gladiator
I think that the article was GREAT for people who are interested in doing everything the hard way.. sometimes i do that myself, so it''s a good read when you have nothing else to do.. Maybe the guy (should i say gal) who made this post doesn''t find it to be a good article, but i''m sure there are many people who do...
Stoffel
Stoffel
I, too, was horrified at the quality of the article.

I''m also horrified by DogFood''s post:
quote:

Something that I do which was not really mentioned in the article is a case of single inheiritance. Example:
typedef struct baseclass {
int x;
int y;
} BASECLASS;
Derived class:
typedef struct newclass {
BASECLASS parent;
int z;
} NEWCLASS;
Now here is where it has power: A pointer to newclass can be typecast to a pointer to baseclass without ANY issues. The compiler formats the beginning of NEWCLASS structure the same way it formatted BASECLASS in memory, therefore any code that uses BASECLASS can work with NEWCLASS(unless you modify the behaviour, but the whole idea is NOT to do so).



Sure, this will get you to inherit members of the base class, but it has several problems:
1) It obfuscates what you''re trying to do. Good luck getting this past code review.
2) I''m pretty sure this will throw compiler warnings (explicit conversion to incompatible type). Where I work, we have a 0 warning tolerance.
3) Common members are not the realy power of inheritence. The power comes in with member function inheritence.

It seems that many people are confused about what problem inheritence/polymorphism is supposed to solve. The problem is this:


// cumbersome type checking
struct Object
{
int type;
// common members, i.e. position, size, whatever;
};

void display_object (Object* pOb)
{
switch (pOb->type)
{
case TYPE_CIRCLE: // do one thing
case TYPE_SQUARE: // do another thing
}
}


In your main loop, you would iterate through a list of Object pointers, and for each call display_object (pOb). This is a prime candidate for polymorphism:

class ObjBase
{
public:
virtual void display () = 0;
protected:
// common members
};

class ObjCircle : public ObjBase
{
// whatever you need in here
};

class ObjSquare : public ObjBase //etc.

Now, in your main loop, you iterate through your list of ObjBase pointers, and call pObj->display () for each, and they each do the right thing.

What''s been added? A vtable to store the function pointer to display (), and an extra indirection to call the function. What''s been lost? Well, you don''t need a switch, you don''t need to tag a type with each object. Probably a pretty even trade-off, both in instructions and memory.

How easy is this to maintain? You need to add your switch case to every function that switches on a type if you want to add or remove object types using the first method. For the second method, you just need to derive a new class.

I hope this has helped some people realize that polymorphism is not just "adding a dereference for no damn good reason to a function call". The example above is the issue for which polymorphism is the tool used to solve.
Gladiator
Gladiator
Hey professor, why don''t you write one and stop insulting people''s work of art...
ImmaGNUman
ImmaGNUman
I dont understand why the guy in the article couldn''t do this:

struct foo
{
int x;
int *y(void);
};

int init
{
struct foo bar;
struct foo baz;

(bar.y()) = (baz.y()) = &y();
}

Bang, you got a fast, slim, multiple instance of a data structure emulating class functionality. Of course, if you wanted private members you would need seperate modules and garbage, but that could easily be done.

-----------------------------

A wise man once said "A person with half a clue is more dangerous than a person with or without one."
-----------------------------A wise man once said "A person with half a clue is more dangerous than a person with or without one."The Micro$haft BSOD T-Shirt
DeltaVee
DeltaVee
What happened to the article? Looks like it was removed.

--------------------------
Carpe Diem
D.V.Carpe Die<FONT C
DeltaVee
DeltaVee
My bad. It was removed from the front page, it is still in the articles page.

oops.

--------------------------
Carpe Diem
D.V.Carpe Die<FONT C

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.