I'll admit that I am new to C/C++ programming. I've been doing my studies via online resources and a few different game programming specific books. The one that I'm currently reading presents its code strictly in C. The best example I can give is that the objects the character controls are defined as structs(). The initial book I read however, was C++ all the way, so it talked of using classes and objects.
I guess my question is are there any advantages to using one over the other?
Again, I apologize for my newbie-ness... Just looking to get off on the right foot.
It depends. C++ is a superset of C, so anything you would do in C you can do in C++. Of course, a good design usually divides the program in objects. For big programs, a class structure really helps. You can easily implement a lot of design patterns in C++ that will make the code better maintainable(sp?) and easily expandible(sp?).
I guess my question is are there any advantages to using one over the other?
None. Just depends which interface you prefer working with.
Someone may be able to come up with some obscure programming feature the C++ way makes easier, but I'm too lazy.
The good thing about structs is that you can bundle related variables into one stucture. These variables are related usually by some object they are modelling. Classes are just an evolution of that, taking it one step further by bundling the procedures that manipulate those variables with the variables themselves. This makes life much easier.
The only real pitfall in choosing C++ over C is that C++ has so many more tricks that you can make it do. This may seem like a good thing, but soon you find yourself spending too much time trying to make C++ do all its nice tricks when all you really wanted it for was C programming with classes. I tend to use C++ just for its ability to use classes. I don't personally overload operators, but I'll happily use classes (such as the D3DX family) that use this feature effectively. I use templates for parameterised classes, but not for any ugly metaprogramming tricks. I avoid multiple inheritence like the plague. The exception is that I sometimes make purely abstract classes and use them like Java interfaces, which can use multiple inheritence.
So my answer would be to use subset of C++ that extends C as far as you want it to and no further.
Of course, a good design usually divides the program in objects. For big programs, a class structure really helps.
This, and on top of it: less typing and more readable code, at least for me.
Using functions:
struct tEnemy { int x,y; }; void enemy_follow_player(tEnemy *e,int px,int py) { e->x += MID(-1,px - e->x,1); e->y += MID(-1,py - e->y,1); }
Using methods:
struct tEnemy { int x,y; void follow_player(int px,int py); }; void tEnemy::follow_player(int px,int py) { x += MID(-1,px - x,1); y += MID(-1,py - y,1); }
Basically, you've just saved some "e->"'s. Also calling it is IMHO more readable:
enemy_follow_player(enemy,px,py); // function enemy->follow_player(px,py); // method
C++ structs are classes that default to private scope.
C++ can be alot safer than C, as long as you know what your doing.
C makes it easy to shoot yourself in the foot. C++ makes it harder, but when you do, you blow off your whole leg.
— Bjarne Stroustrup
It's probably THE most tricky question one could ever ask 
I'd say, when you encounter a case that resembles something you saw in C++, try the C++ method.
Any time you're going to dynamically allocate and free stuff, C++ classes would probably be safer (there are less different ways to do something wrong)
One case where you'll be happy to use C structs is whenever you want to put constant data in the source itself:
typedef struct { char * name; int level; int hp; int xp_reward; } S_ENEMY; S_ENEMY enemy_table[] = { { "goblin", 1, 15, 100 }, { "dragon", 10, 200, 1000}, { NULL, 0, 0, 0 } };
Array size computed at compile time, data automatically initialized before main().
It's almost impossible to go wrong there
You forgot the other option: Assembler. This is by far the easiest language to do OOP in. Not the easiest language at all, but you can do something like THIS(16-bit x86 ASM):
| 1 | mov bx,StartPointers |
| 2 | mov cx,[CountPointers] |
| 3 | LoopStart: |
| 4 | push bx |
| 5 | push cx |
| 6 | push cs |
| 7 | mov ax,ReStartPos |
| 8 | push ax |
| 9 | mov ax,[bx] |
| 10 | push ax |
| 11 | mov ax,[bx+2] |
| 12 | push ax |
| 13 | mov dx,[bx+4] |
| 14 | retf |
| 15 | ReStartPos: |
| 16 | pop cx |
| 17 | pop bx |
| 18 | add bx,0006h |
| 19 | loop LoopStart |
Then again, ASM is bloody hard for a first-time programmer. But if you can code ASM, you can make SURE it does what it's supposed to. But if you can do OOP in C, then you've officially mastered the core aspects of C. C++ is lazy, as miran was with the AMGC2, which only supports C++, and not a standard DLL.
But really, who NEEDS classes?
typedef struct { int x,y; BITMAP *sprite; } Noob; void followplayer(Noob *n,int ex,int ey){ n->x+=(ex<px?1:-1); n->y+=(ey<py?1:-1); }
(that (ex<px ? 1 : -1) is (if_this_is_true ? give_this : else_give_this))
But it's your own personal preference. I prefer C because it's simpler, and you can ignore all that "using namespace std" crap. If you are really good at JavaScript, take C.
I think the C++ programmers are trying to persuade you to take C++.
More readable code? What a load of crap. They're virtually the same for readability.
I think the C++ programmers are trying to persuade you to take C++.
You say that as though it's different from a C programmer trying to persuade him to take C...
But if you can do OOP in C,
Stop right there. You can't do OOP in C, not really. C has limited inheritance, even more limited encapsulation and no polymorphism. OOP is more than just classes, and C doesn't even have that.
You can't do OOP in C, not really
OOP is a programming methodology, not a language-specific feature. You can very well do OOP in C. Allegro is an example of this.
Only wanted to restate...
C with structs or C++ with classes (...) are there any advantages to using one over the other?
now one answer to thematrixeatsyou:
More readable code? What a load of crap. They're virtually the same for readability.
I don't agree. Being able to refer it "itself" by typing "x, y, hp" instead of "p->x, p->y, p->hp" may seem petty, but in my game it spared me about 200 times typing the "p->", just for the player and one missile. By the time the game is finished, it'll be 1500 times. That's a net benefit to me.
Wow, I didn't expect to get so much input. Thanks everyone...
It depends. C++ is a superset of C, so anything you would do in C you can do in C++. Of course, a good design usually divides the program in objects. For big programs, a class structure really helps. You can easily implement a lot of design patterns in C++ that will make the code better maintainable(sp?) and easily expandible(sp?).
That's the impression I was getting, based off just sort of comparing code from the C-centric book and thinking, "how would this be setup with OOP." I really want to think as progressively as possible in my coding, and while I know C++ is based on C, C++ is more or less the standard coding language for games these days.
The only real pitfall in choosing C++ over C is that C++ has so many more tricks that you can make it do. This may seem like a good thing, but soon you find yourself spending too much time trying to make C++ do all its nice tricks when all you really wanted it for was C programming with classes.
I get what you're saying. I'm well aware that my C++ know-how is probably less than 10% of what I can actually do with the language. I've been doing my best to step into the deep-end slowly instead of just diving headlong. 
I don't agree. Being able to refer it "itself" by typing "x, y, hp" instead of "p->x, p->y, p->hp" may seem petty, but in my game it spared me about 200 times typing the "p->", just for the player and one missile. By the time the game is finished, it'll be 1500 times. That's a net benefit to me.
This may be true, but I can also see the other side of the argument. For example, the C-centric book I mentioned defines its two player objects as structs like this:
players[num].x - X position
players[num].y - Y position
players[num].score - Score
players[num].dir - Direction
In this instance, num is an int that defines either player one -- index 0 -- or player two -- index 1. While it makes perfect sense to me, I abhored having to write "players[num]" five hundred times when changing or checking attributes. It'd be so much simpler to do with C++:
player1->x
player2->y
etc. etc.
I definitely see both sides of this. I find myself leaning towards C++, if only to stay progressive, but I do really appreciate everyone's input on this topic.
Wow, I didn't expect to get so much input. Thanks everyone...
Welcome to Allegro.cc!
definitely see both sides of this. I find myself leaning towards C++
They don't call it C/C++ for nothing. You're better off knowing both (which shouldn't be that hard once you get one down) and using whatever fits the task at the time IMHO.
[EDIT]
Most game-wise stuff, I like more C++ standards. It's more modular and easy to construct a sensible design, which is why I think it is typically used for today's games. However, in the business world, C is still commonly used (basically, all that class stuff just isn't needed for what they want).
I just found out I can use C modules with Informix 4gl (which is what I do at work) and I'm ecstatic even though I prefer C++.
OOP is a programming methodology, not a language-specific feature. You can very well do OOP in C. Allegro is an example of this.
I never said it was a language-specific feature, I said C wasn't fully capable of it, and it isn't. Allegro takes an object oriented approach, certainly, but it falls a little short. Look it up in any text you like; "real" OOP requires encapsulation, inheritance, and polymorphism. C can approximate these, but only to a certain degree. OOP requires certain language features, and C doesn't have them.
[EDIT]
Lest people start jumping all over me with arguments about why C is better, notice that I'm not taking a stance either way, I'm simply pointing out the fact that C++ has some features that C does not. That, in and of itself, does not constitute an argument that one is better than the other, it's just statement of fact. Arguing that C is OOP doesn't make it so.
Now, I'm the president of "C++ has too many features", but in the end it doesn't really matter, because it still adheres to the spirit of C that says, "if you don't want it, don't use it". I prefer C++ because it gives me the features I want, and doesn't force me to use the ones I don't (for the most part).
Welcome to a C vs. C++ thread!
Fixed.
players[num].x - X position players[num].y - Y position players[num].score - Score players[num].dir - Direction In this instance, num is an int that defines either player one -- index 0 -- or player two -- index 1. While it makes perfect sense to me, I abhored having to write "players[num]" five hundred times when changing or checking attributes. It'd be so much simpler to do with C++: player1->x player2->y etc. etc.
Note that the code you posted above is 100% C, in both cases.
There's no reason to use an array to access objects in C if you don't want to. C is perfectly capable of accessing said objects through pointers, as described in the second part of your example. I do this quite a lot in my C code.
_Dante: C is perfectly capable of all of the OOP features that you describe. Approximation? The resulting code may not look like what you'd see in C++, but the functionality is similar if not identical. I've successfully encapsulated, templated, polymorphed, and inherited using C. As well, certain things like prototyped OO, which is not supported in C++ directly, are just as easily accomplished in C as the rest of the OO features. My final advocacy for the C way of doing things is freedom.
Many things that are frowned upon in C++ land are perfectly acceptable and embraced in C. If you want to be rigidly restricted to a certain way of thinking, spend a lot of time designing the perfect class hierarchy, then embrace the C++ OO methodology. If, like me, you'd rather dispense with the handcuffs and pedantic fluff that gets in the way of actually creating a game, then try the C way.
But if you can do OOP in C,
Stop right there. You can't do OOP in C
Oh yes you can. Doing OOP in C does not require the usage of all of C++'s features in C. However, while OOP is possible in C, it can be a bit tedious at times. I'm currently working on a C program that I started some time ago, and I'm gradually making it more and more C++ like by using an OOP design.
The example that Krzysztof posted is how you would emulate objects (combining methods and data) in C. To make it clearer to read and see which is the object being worked on, you could call the pointer to the object some variation on 'this' (I use Hungarian notation), so 'This' becomes 'epThis' (I've only bothered with turning 'epThis' into Hungarian notation), the code becomes...
struct tEnemy { int x,y; }; void enemy_follow_player(tEnemy *epThis,int px,int py) { epThis->x += MID(-1,px - epThis->x,1); epThis->y += MID(-1,py - epThis->y,1); }
It is possible to go further in C. Inheritance can be emulated in C too. Immagine if the enemy has multiple behaviour patterns depending on it's state. Just include a function pointer in the struct, and change this function pointer depending on the state.
| 1 | typedef void(TtBehaviourFunction)(tEnemy *epThis, int px, int py); /*!< Shortcut for a function-pointer to an enemy-behavour function */ |
| 2 | |
| 3 | struct tEnemy { |
| 4 | int x,y; |
| 5 | TtBehaviourFunction *fpBehaviour; |
| 6 | }; |
| 7 | |
| 8 | void enemy_follow_player(tEnemy *epThis,int px,int py) |
| 9 | { |
| 10 | epThis->x += MID(-1,px - epThis->x,1); |
| 11 | epThis->y += MID(-1,py - epThis->y,1); |
| 12 | } |
| 13 | |
| 14 | void enemy_avoid_player(tEnemy *epThis,int px,int py) |
| 15 | { |
| 16 | epThis->x -= MID(-1,px - epThis->x,1); |
| 17 | epThis->y -= MID(-1,py - epThis->y,1); |
| 18 | } |
| 19 | |
| 20 | void enemy_setup(tEnemy *epThis) |
| 21 | { |
| 22 | /* ... */ |
| 23 | epThis->fpBehaviour = enemy_follow_player(); /* This is the initial enemy-behaviour - change according to state */ |
| 24 | } |
| 25 | |
| 26 | |
| 27 | void do_logic() |
| 28 | { |
| 29 | epEnemy->fpBehaviour(epEnemy, px, py); /* Do the enemy's behaviour method */ |
| 30 | |
| 31 | if(state_changed()) |
| 32 | { |
| 33 | if(state==foo) |
| 34 | { |
| 35 | epEnemy->fpBehaviour = enemy_avoid_player; /* Change the behaviour of the player */ |
| 36 | } |
| 37 | else if(state==bar) |
| 38 | { |
| 39 | epEnemy->fpBehaviour = enemy_follow_player; /* Change the behaviour of the player */ |
| 40 | } |
| 41 | } |
| 42 | |
| 43 | |
| 44 | } |
Here, it is as if fpBehaviour is a virtual function. Just set it to point to a method for dealing with player behaviour. If you have several methods that change at once, changing all these methods can be a bit time consuming, so what we do is to use a structure called a vtable. This is a structure of function pointers that are associated with a particular state. So if the state changes, instead of changing a whole bunch of function-pointers, just change the vtable. An example...
| 1 | typedef void(TtBehaviourFunction)(tEnemy *epThis, int px, int py); |
| 2 | typedef void(TtAnotherBehaviourFunction)(tEnemy *epThis, int foo); |
| 3 | typedef int(TtStateGettingFunction)(tEnemy *epThis); |
| 4 | |
| 5 | struct tEnemyBehaviourVtable |
| 6 | { |
| 7 | TtBehaviourFunction *fpBF1; |
| 8 | TtBehaviourFunction *fpBF2; |
| 9 | TtAnotherBehaviourFunction *fpABF; |
| 10 | TtStateGettingFunction *fpSGF; |
| 11 | }; |
| 12 | |
| 13 | tEnemyBehaviourVtable vtBehaviourVT1 = |
| 14 | { |
| 15 | enemy_follow_player, |
| 16 | enemy_follow_player_quickly, |
| 17 | enemy_make_noise, |
| 18 | enemy_get_aggression, |
| 19 | } |
| 20 | |
| 21 | tEnemyBehaviourVtable vtBehaviourVT2 = |
| 22 | { |
| 23 | enemy_avoid_player, |
| 24 | enemy_avoid_player_quickly, |
| 25 | enemy_make_squeak, |
| 26 | enemy_get_fear, |
| 27 | } |
| 28 | |
| 29 | struct tEnemy { |
| 30 | int x,y; |
| 31 | tEnemyBehaviourVtable *vtpBehaviour; |
| 32 | }; |
| 33 | |
| 34 | |
| 35 | void enemy_setup(tEnemy *epThis) |
| 36 | { |
| 37 | /* ... */ |
| 38 | epThis->vtpBehaviour = vtBehaviourVT1; /* This is the initial enemy-behaviour - change according to state */ |
| 39 | } |
| 40 | |
| 41 | |
| 42 | void do_logic() |
| 43 | { |
| 44 | epEnemy->vtpBehaviour->fpBF1(epEnemy, px, py); /* Do one of the enemy's methods */ |
| 45 | epEnemy->vtpBehaviour->fpABF(epEnemy, nFoobar); /* Do another one of the enemy's methods */ |
| 46 | |
| 47 | if(state_changed()) |
| 48 | { |
| 49 | if(state==foo) |
| 50 | { |
| 51 | epEnemy->vtpBehaviour = vtBehaviourVT1; /* Change the behaviour of the player */ |
| 52 | } |
| 53 | else if(state==bar) |
| 54 | { |
| 55 | epEnemy->vtpBehaviour = vtBehaviourVT2; /* Change the behaviour of the player */ |
| 56 | } |
| 57 | } |
| 58 | |
| 59 | } |
While a vtable only involves changing a single pointer instead of a set of pointers, it also means the code has to make an extra dereference.
So in answer to the original question "C with structs or C++ with classes... Your choice and why.", I'd say "Whatever you feel the most comfortable with". But saying that, I'd encourage programmers to experiment with new programming paradigms from time to time - OOP being one of them.
AE.
Apples and Oranges.
I'm well aware of how to emulate objects in C and do most of what everybody has pointed out here. I would still argue that everything posted to this point still "approximates" polymorphism and encapsulation. Calling a particular function in a switch statement isn't polymorphism, it's essentially an if-else construction. The true power of polymorphism comes from the parent class needing absolutely no knowledge of the child class, other than the fact that it inherits a virtual method from the parent. So calling something like;
object->doSomething();
will always result in the correct behaviour, and I didn't have to touch the parent class or the calling code to accomplish it.
True encapsulation requires information hiding, and C is not capable of this. If there's a member in your C "class", I can access it if I can find it (and with most modern IDEs, I can most certainly find it).
If you don't agree with all of that (or I'm simply out-and-out wrong), my final argument as to the superiority of C++ over C in an OO context, it does make all of this much easier. You're given a this pointer, v-tables, quick & easy inheritance, encapsulation, etc, etc. Why re-invent the wheel?
Lastly, to Paul Pridham: C++ offers the same freedom that C does. C++ is a superset of C - anything C can do, C++ can do. Admittedly, you need an extra cast here and there because the compilers are more strict, but as I mentioned before, C++ gives me the features I want, and allows me to ignore the ones I don't. Simply because something is frowned upon by a particular group, doesn't mean it's prohibited by the language. Nobody's holding a gun to anybody's head to "design the perfect class hierarchy" (except maybe Grady Booch).
If you find yourself making C do C++ things, then perhaps it's easier to use C++. You can still use C withing C++, so you lose nothing by doing this.
As far as C giving more freedom, that's a complete fallacy. The truth is the C++ gives compiler warnings potentially where C doesn't, but it compiles the code anyway. For example, C will happily let you implicitly convert a float to an int, potentially losing precision. C++ will warn you about this possible loss in precision, but will let you do it anyway. An explicit cast will turn off this warning and show readers of the code that a conversion is taking place.
However, if C++ was actually being restrictive, that would only be a good thing. Freedom in programming languages gets you into trouble. The right amount of restriction actually increases productivity and expressivity because you know there are certain errors that you cannot make in some more restrictive languages that you can make in some less restrictive languages.
I get what you're saying. I'm well aware that my C++ know-how is probably less than 10% of what I can actually do with the language. I've been doing my best to step into the deep-end slowly instead of just diving headlong.
My C++ know-how is probably within the 10-25% range. That, combined with my ~85% C knowledge is more than enough for me to be productive in C++. There's no need to learn more. The design philosophy behind C++ is that it's a better C. That's precisely how I use it.
But if you can do OOP in C, then you've officially mastered the core aspects of C. C++ is lazy, as miran was with the AMGC2, which only supports C++, and not a standard DLL.
That's a great philosophy you've got there.
"Always do it the hard way!" C isn't an object oriented language, therefore object oriented programming is not one of it's core aspects. If you design your code to be object oriented that's great, but what's the point of taking a system that was designed to be used one way, and forcing it to do something else? In Allegro's case it's fine, since it's oriented toward a wider audience. But there is nothing lazy about using your tools they way they are intended to be used, especially when your job is to make something quickly that's both fast and efficient.
I prefer C because it's simpler, and you can ignore all that "using namespace std" crap.
It looks like you are the lazy one here.
You forgot the other option: Assembler. This is by far the easiest language to do OOP in. Not the easiest language at all, but you can do something like THIS(16-bit x86 ASM):
Is it really? I honestly doesn't see how it could be. I personally don't know how to program in it, but I've read quite a bit on the topic and I know enough to question the validity statement. I don't quit know what the code you posted accomplishes, but it certainly doesn't look like it does anything amazing.
Although you can program in C++ in the same manner as C, there is often a difference in programming approaches (procedural v Object Orientated). This is the biggest difference for me (and the hardest to adapt to).
To me it seems like the C++ approach is more complicated only if you are coming at it from a C point of view. Good OO code should be simple and straightforward. It should explain itself. However, I often find myself going way overboard with it, i.e., using all the C++ features I can in hopes that it will make my code more robust. It usually ends up like a big bowl of spaghetti code, exactly what OO code isn't supposed to be.
Object is a matter of how you mind your code. The language is a plus, but if you are thinking OOP, you code OOP. You can't say that because the way of coding is different it can not be OOP. It is just that your mind is too close for accepting the fact. You can code in what you want, the processor just have a limited couple of instructions.
Some can prefer C, other C++,pascal,basic,C#... I personally prefer C. And so ? You can not live knowing that other don't use the same tool than you ? Héhé.
I love those fights. The result is always the same, but I love.
What is this, the fourth C vs C++ thread this week?
What is this, the fourth C vs C++ thread this week?
Something like that.
Some can prefer C, other C++,pascal,basic,C#... I personally prefer C. And so ? You can not live knowing that other don't use the same tool than you ? Héhé.
Not sure who that question was aimed at, but I'd like to answer it anyway. 
I really don't care what other people use. If they want to use C, that's fine. C++ is fine as well. Hell, if you want to use BASIC you can. Te me it just seems a little dumb to spend all this time trying to emulate useful features in one language when they have already been fully implemented into another, almost identical language.
Plus, at the end of the day, what's wrong with being a little lazy? If I (in a general sense) can produce as good or better results in much less time, what's there to be ashamed of?
I do not say we should not have do this thread .
EDIT: Jonny Cook : Héhé ;-)
That makes two of us...
If you find yourself making C do C++ things, then perhaps it's easier to use C++.
Unless you're working on an existing C project. Converting an entire project from C to C++ (even if it's object-oriented C) can take so much time that it would be more productive to use OO C. But I agree that if you like OOP, then you should start new projects in C++.
That's a great philosophy you've got there.
"Always do it the hard way!"
I have a syaing in life. If it isn't worth doing the hard way, it's not worth doing at all.
AE.
Agreed
The truth is the C++ gives compiler warnings potentially where C doesn't, but it compiles the code anyway.
There are certain cases where my compiler requires a cast. For instance, assigning a void pointer to anything but another void pointer is not allowed:
g++
error: invalid conversion from `void*' to `TestStruct*'
msvc
error C2440: 'initializing' : cannot convert from 'void *' to 'TestStruct*'
armcpp
Conversion from 'void*' to pointer to non-'void' requires an explicit cast
That notwithstanding, I still agree with Steve++ in that the few restrictions the language itself puts on you are actually a good thing (think type safety), and in the end you do what you need to do quickly and cleanly.
I don't know how many ways I can say this, but I'll try one last time. Writing in C++ doesn't require any OOP. Or templates. Or streams, or MIL's, or feature X. It has lots of features that make OOP easier - much easier - than a language not designed for it, but it's still essentially C with extra stuff. Use the stuff you like, ignore the stuff you don't.
I have a syaing in life. If it isn't worth doing the hard way, it's not worth doing at all.
I have one, too (shamelessly stolen from Three Dead Trolls in a Baggie):
"Yeah, but I've got a girlfriend, and things to get done."
Calling a particular function in a switch statement isn't polymorphism, it's essentially an if-else construction.
And what do you think the compiler is doing behind the scenes? ie 'late binding'?
And I'd also point out that c++ wasn't the first object oriented language base on c, objective c has a completely different way of implementing oop on top of c. I'd recommend looking at it if you (all) haven't, it gives you a nice perspective.
Dante: Nobody said anything about C needing case statements for OOP. Not that using them isn't a valid way to do OOP stuff, because you can certainly do it that way. However, I usually use a vtable, or "interface" (struct of function pointers). Polymorphism can come from calling through a different, but compatible interface. Or, it can come from using a different set of functions to operate on the functionally compatible data structure (through casting). Really, using function pointers, you can come up with all sorts of different OOP schemes. Prototype an object by copying it (along with function pointers) and then changing the pointers or data pointed to by the new object. Etc. This kind of thing isn't written into either language, but C++ directs you to a certain kind of OOP usage, while C does not. Earlier, I implied that C++ was dogmatically restrictive. Sure, you can write code any way you want in C++, the "superset" of C. It just tends towards certain trends and design patterns.
C++ does a lot of things implicitly, and C explicitly. I prefer explicit control when it comes to language features and behaviour. C makes less assumptions, leaving me free to make my own. Of course, if all of these "languages" just had a Forth precompiler, we wouldn't be having this discussion. 
And yes, aren't we all sick of this debate already...
And what do you think the compiler is doing behind the scenes? ie 'late binding'?
Don't know, don't care. That's the point - the compiler can do what it likes, as long as it's compliant.
Nobody said anything about C needing case statements for OOP. Not that using them isn't a valid way to do OOP stuff, because you can certainly do it that way.
Nobody said needing, fair enough. But suggesting that a series of switch statements constitutes polymorphism? Any language with an if/else construct can do that. I'm gonna have to strongly disagree.
The person posing the original question (remember him?) stated that he was new to the language. You can't seriously suggest that he should attempt to implement all sorts of complicated features when C++ gives it to him for free. The question was, are there any advantages to using one over the other? The advantage of using C++ is that it has all the features of both languages, so you have lots of choices. The advantage of using C is... some perceived control that apparently isn't available in C++.
I can't imagine what explicit control buys you, but whatever makes you sleep better.
And yes, aren't we all sick of this debate already...
Totally. But as everybody knows, the most important thing is to be right (or at least perceived right), which means one can't possibly let the other guy have the last word
I can't imagine what explicit control buys you
Peace of mind. And control. Its all about control.
I can't imagine what explicit control buys you, but whatever makes you sleep better.
Some constructs just can't be expressed be plain direct-hierarchy OOP. You really want to custom-build classes. You could switch to another language which allows it, or you can just manually build a vtable, C style.
I use C++ and for cleanliness reasons, I use structs for grouping data (sound as a 'point' or 'vertex') and classes for interactable objects - be like me.
If using c++ then i will make full use of classes rather than structs.
this
class Array<T,int dim> { typedef Array<T,dim> array; T[dim]; public: Array(const array& copy); T& operator[](size_t index); operator=(const array& assign); bool operator==(const array& equals); bool operator!=(const array& notEquals); swap(array& swapWithMe); size_t size(); //returns "dim". };
is certainly a lot easier to worth with than just a straight array. Since you are talking about structs vs classes image a case where you were dealing with strings
typedef struct string { char* dat; size_t length; } string;
or
| 1 | class string |
| 2 | { |
| 3 | char* dat; |
| 4 | size_t length; |
| 5 | public: |
| 6 | string( const string& a ) //copy |
| 7 | /* more useful constructors */ |
| 8 | |
| 9 | trim(), regex(), //other shit too |
| 10 | |
| 11 | //various operators |
| 12 | operator= |
| 13 | operator== |
| 14 | operator> |
| 15 | operator[] |
| 16 | |
| 17 | const char* c_str(); // |
| 18 | } |
Both have the same memory layout (this is a POD class, aka plain ol' data). The memory layout would change if you have virtual (a table would be needed).
C is for people that think beards are cool.
And AJ is a name for Big Baby Boys ! ;-D
I never said it was a language-specific feature, I said C wasn't fully capable of it, and it isn't.
You said:
You can't do OOP in C
which is 100% false, no matter how you look at it. You can very well do OOP in C. As a language, C may not be designed with OOP in mind, but there is nothing standing in your way to take a fully OOP approach with programs written in C. It may just take a little extra grunt work. Inheretence, encapsulation, and polymorphism are not required for OOP, they simply make it easier.
But it's your own personal preference. I prefer C because it's simpler, and you can ignore all that "using namespace std" crap.
That shows that you know nothing about C++.
the std namespace is an API, it has nothing to do with C++ itself.
More readable code? What a load of crap. They're virtually the same for readability.
At times, C++ can be more readable (if you're the one writing the code). But if you look at some C++ that uses all kinds of C++'s features, and you didn't write it, you can spend hours trying to understand what it does.
Inheretence, encapsulation, and polymorphism are not required for OOP, they simply make it easier.
You had me right up to this statement. I take back the "C can't do OOP" part, I've been shown the error of my ways, but what I really meant to say originally was basically that C isn't really an OO language - and I still stand behind that. The facilities to do OOP are not an inherent part of the language. Being able to accomplish OOP with it doesn't make it an OO language any more than strapping a penguin to a rocket makes it able to fly.
All that aside, the claim that inheritance, encapsulation, and polymorphism are not required for OOP is simply incorrect. These things aren't suggested features, they're part of the definition.
Unless you're working on an existing C project. Converting an entire project from C to C++ (even if it's object-oriented C) can take so much time that it would be more productive to use OO C.
So you spend half a man hour renaming everything from .c to .cpp and compiling everything, casting any void pointers that the compiler may complain about. Is that half a man hour such a big price to pay for having language supported OOP at your disposal instead of doing it the hard way in pure C?
Like the others here that are actually speaking sense, I'm not supporting C++ over C or vice versa. All I'm saying is that if you want to do OOP, use a language that natively supports a reasonably large subset of the paradigm. Almost all C++ programmers are aware they could do OOP in C if they wanted. Big deal.
C is a good procedural language and I will use it when I have a good enough reason to. There are times when I don't particularly care for C++'s strict type checking.
But suggesting that a series of switch statements constitutes polymorphism? Any language with an if/else construct can do that. I'm gonna have to strongly disagree.
Sure. You can implement polymorphism using switch/case or if/else, using run-time type information and delegation, for example. I'm not saying it's pretty, but it's certainly possible. You can disagree if you want, but you're still wrong.
The person posing the original question (remember him?) stated that he was new to the language. You can't seriously suggest that he should attempt to implement all sorts of complicated features when C++ gives it to him for free.
No. I don't suggest that he implements anything complicated... far from it. I suggest that the C programming mindset produces simpler code by eliminating many potentially misleading language/design pitfalls, and that C++-style OOP is possible if you want it. As well, you can produce "object-based" programs that doesn't need to adhere to the full compliment of OOP dogma too, which again can simplify things.
His original question was whether to use structs or classes. Well, I say structs. And so...
David_at_wedu: Keep it simple, and don't get distracted with overdesign and language purity. This is just my opinion, though, and it's evident that everybody has one of their own.
Is that half a man hour such a big price to pay for having language supported OOP at your disposal instead of doing it the hard way in pure C?
I'll pay you $100 to port Allegro to C++. As I'm generous I'll give you a whole day to do it
I actually find this whole debate pretty funny.
You're all arguing as if C++ is a pure OO language, while C is a more flexible language that you could perhaps implement OO inside.
Not true! C++ is a multiparadigm language. So is C, but a far simpler one. A more meaningful debate would be between small and simple versus bloated and powerful.
Of course it is true that you can do OO in C, but it is also totally true that you can write procedural or functional code in C++. And that's no accident: C++ was designed to be a big tent, not a pure OO language. In fact it has at least as many features geared toward functional programming as it does to polymorphic class hierarchies, as explained by the father of the whole thing:
http://www.research.att.com/~bs/ieee_interview.html
http://linux.sys-con.com/read/32929.htm
If you want a pure OO language, try here:
http://c2.com/cgi/wiki?SmalltalkLanguage
(or arguably Java / Ruby)
I used to use C until I discovered vectors. Now I use C++ purely because I don't have to bother with all this malloc() crap. But, I also do the bad programming practice (as I've heard it called somewhere) of 'using C++ as a better C'. To me there's nothing wrong with that. I'd use C if it had an equivalent of vectors.
That's not a bad programming practice at all! The man himself (Stroustrup) encourages a mixed paradigm programming style, using whatever features make sense for you.
That is simultaneously the greatest strength and the greatest weakness of C++.
A strength because it gives huge flexibility. Don't like exceptions? You don't have to use them. Don't like the standard memory allocator? You can replace it. Don't like virtual methods? They're optional. You can use it like Smalltalk, or as a better C, or as a compile time metaprogramming language, or a million things in between.
But a weakness because everyone ends up using it in a slightly different way. That makes it really hard to reuse third party C++ libraries, because the chances are they're returning error codes while you are using exceptions, and their memory allocator is different to yours.
That flexibility is a problem in C, too, because it is also a very flexible multiparadigm language. Flexibility is good until you want to reuse code, which is a large part of why Java and C# lock things down a bit more tightly (thou shalt use garbage collection, and thou shalt use exceptions to report errors, and thou shalt use the builtin string type, not one you just made up yourself, and thus shall all thine libraries play nicely together).
Personally i write container classes and follow a "pipe and filter" paradigm most days. The best part of OOP in my mind is for wrapping up data. It makes things so nice and clean.
The full OOP paradigm though with UML, use cases, everything a class and obj a using obj b is needlessly complicating things for what i do.
C++ allows me to just do that. But i must admit that a language like c# makes a really nice one to write desktop applications with.
You can implement polymorphism using switch/case or if/else, using run-time type information and delegation, for example.
Touché. Using RTTI would certainly fill the bill (I'd opt for function pointers, but hey, that's just me). But a manually built if/else construct that requires me to add one more case for each additional subclass doesn't constitute polymorphism in my books. Whether I'm wrong about that is just semantics.
If fact, arguing about whether any particular language is OO, or procedural, or (name your methodology here), pretty much comes down to semantics. One could argue that the Intel instruction set encompasses all of these methodologies, because after all, you can accomplish all of those things with it, can't you? I'm going to agree to disagree on what sort paradigm any particular language follows, because we're not all going to agree on what the requirements are. We've reached the "Oh yeah?" "Yeah!" "Oh yeah?" "Yeah!" stage of the argument, and it's not interesting anymore.
Definitely agree with Shawn, his voice is probably one of the more sane in this particular thread, his love of C# notwithstanding
. I've made the same point a number of times here - don't like a language feature? Then don't use it. Which is still my chief argument for using C++ over C. You get all the features of C, plus a bunch of other optional ones. Choice is good.
Java and C# (and lots of others, I'm sure) definitely "lock things down" a little more, although even some of those safe-guards can be short circuited. Dogma surrounding a language doesn't make it capable or incapable of anything; if you want to use return values to report errors in Java, there's nothing really stopping you. I've seen people write code that amounts to something like:
public static void main(String argv[]) { try { // entire program here } catch(Throwable t){} }
(No, I've never seen anything quite that blatant, but if all of your catch blocks use Exception and are empty, then it amounts to roughly the same thing.)
Definitely agree with Shawn, his voice is probably one of the more sane in this particular thread
I can't imagine anyone who creates something as great as allegro could really be...sane.
Java and C# (and lots of others, I'm sure) definitely "lock things down" a little more, although even some of those safe-guards can be short circuited. Dogma surrounding a language doesn't make it capable or incapable of anything; if you want to use return values to report errors in Java, there's nothing really stopping you.
This runs into the fuzzy line between technology and culture.
People don't often think of culture as an important part of a language, but really it is. That affects things like naming conventions and code layout, but also larger scale design patterns, where you go to find reusable code, who will help you when you get stuck, and so on.
In the same way as it doesn't force a single technological style, C++ doesn't have a single cuture either. Hence the endless holy wars over where to put your braces, but also this tends to make third party code feel very alien and often unnatural if you sit it alongside your own.
More modern languages (in which I would include Perl, Python, Ruby, etc, as well as Java and C#) tend to have much stronger and more unified cultures. Partly that's just because they haven't had so much time to diverge, but also I think there is some deliberateness on the part of the language designers. Since the rise of the internet, community is seen as very important, so languages are much more likely to have a few centralized hub sites, more in the way of tutorials and FAQ's and example code, and this all points people toward a more unified way of using the language.
That's certainly something Microsoft are very aware of. In addition to the technical decision that all the .NET framework will use exceptions rather than error codes, they put a lot of energy into making sure that the documentation and samples are aligned with that, and finding ways to encourage the whole community to adopt a more unified approach.
Is that a good thing? It's like the programmer version of globalization, and the same arguments apply as out in the wider world. In a way it is a shame to loose all the colorful local flavor and unique ways of doing things, but in practical terms, it is seriously useful to have a common language and be able to communicate and share with people from all over the world...
C is for people that think beards are cool.
I must disagree here, I have a beard and I prefer C++.
Which gives me a wonderful idea: rather than argue about C vs C++ for the nth time, let's argue about beards instead. I, for one, am rather pro-beard, though I do accept that it does have some drawbacks which are more easily solvable using a non-beard paradigm.
HAHAHAHA! [Laughing my *** off]
For some reason that had me hysterically laughing!
This thread is fun to read.
Beards are definitely where it's at for me. I've been working within the beard framework for years, and it's never let me down.
If you think about it, beards are a big part of the culture that Shawn describes; though much as it pains me to admit it, beards seem to represent the old school. Think about it - old school thinkers, like the Greeks: beards. Modern thinkers, like Newton (maybe not so modern, but at least this millennium), Einstein, Hawking: no beards.
Old school computer science - Ritchie, Thompson, Kernighan, Wozniak, Stroustrup: beards. Modern computer science - Bill Joy, Larry Wall, John Carmack, Michael Abrash: no beards.
Sure, there's exceptions, but those only prove the rule, don't they? Not sure where a mustache places you, probably somewhere in the middle.
I think you're missing the point. A good framework really shouldn't care whether or not the author had a beard. The important issue is how easy it is for users to customize, extend, or replace the facial hair. This is where functional techniques really come into their own. Have you ever tried using a disfunctional razer? No fun at all, trust me on that.
Excuse me for interrupting your discussion about beards...
But Shawn, how do I write a... MIDI message processor function?
I lean towards simplicity where my grooming interface is concerned - Wilkinson Sword is a fairly robust implementation, and it does what I need it to do. That being said, I think it's flexible enough for most facial hair paradigms, whether it be hairless, goatee, or full facial coverage (but clean below the neckline).
I can't believe you would hardcode your grooming implementation to depend a fixed worker type like Wilkinson Sword. Down that route lies tight coupling and unmaintainability in the face of changing business requirements. At the very least you should have your concrete razor type be a specialization of an abstract superclass. It also seems like the visitor pattern could be a good fit here, assuming you don't want to go the whole hog and implement a full on barber interface.
Beards can be nice but just add bloat to mustache ride functionality. Using beards increases the computational complexity of such a vehicle and turns an O(1) ride time into an O(nlogn) ride time. The additional workload can be increased so much that in some cases thick beards are not even tractable.
Don't be ridiculous: beards are linear!
Unlike bad haircuts. It is well known that understanding why anyone would choose to have a mullet is NP-hard.
assuming you don't want to go the whole hog and implement a full on barber interface
I have tried a barber interface on a couple of occasions, but found it to be too expensive an operation for my tastes. My current interface serves me well, mostly because it's a legacy platform, and I have no plans to upgrade. I've considered a going with a simple mustache or hairless paradigm, but my Nookie Provider claims some sort of incompatibility and has threatened to cancel my account, or even switch to an entirely different platform.
Sometimes you just gotta go with what works.
Not having a beard, nor mustache, nor hair solves the Sleeping barber problem [1]
Sometimes you just gotta go with what works.
Some/Most times the Nookie interface itself incurs huge costs all by itself.
http://www.research.att.com/~bs/ieee_interview.html
Does anybody else read that as "home of BS"?
Sometimes you just gotta go with what works.
Some/Most times the Nookie interface itself incurs huge costs all by itself.
Can't argue with that. However, the overhead associated with creating a new object is a lot more expensive than the maintenance of a currently existing one.
That would be included in the overall maintenance costs
It's not just the constructor overhead you have to worry about when switching provider, though. There are also a bunch of resource management issues when it comes to disposing of the previous instance.
The simplest approach is just to let the garbage collector to deal with this for you, but that can lead to unpredictable resource consumption while a potentially unbounded number of previous relationships are awaiting finalization.
Reference counts are simple and seem to work ok in practice, but don't deal well with cyclic structures so are best avoided unless you are strictly monogamous.
Old skool coders will argue in favor of manual cleanup, which is incredibly efficient but also very dangerous because it is so easy to accidentally leak resources like your house, car, kids...
Reference counts are simple and seem to work ok in practice, but don't deal well with cyclic structures so are best avoided unless you are strictly monogamous.
Which is why people use shared pointers and weak pointers.
I've never really been into the whole boost::shared_ptr<> scene, but each to his own I suppose...
And why anyone would want to use/have a weak_pointer<> is beyond me.
One of our interns is a Python freak, and he claims it uses them all over the place. I don't recall what precisely the usage is (he's not here today), but Pygame does seem pretty nifty.
Shawn, quit being so funny, I'm not getting any work done.
How on earth did we end up talking about snake fetishes? I can think of a lot of things you could do with a snake, with or without weak and/or shared pointers, but I don't think I'd particularly enjoy any of them...
Leather, on the other hand, now that's something I can relate to.
How on earth did we end up talking about snake fetishes? I can think of a lot of things you could do with a snake, with or without weak and/or shared pointers, but I don't think I'd particularly enjoy any of them...
Leather, on the other hand, now that's something I can relate to.
Sheesh, no imagination - what's wrong with snakeskin leather?
Unless you're working on an existing C project. Converting an entire project from C to C++ (even if it's object-oriented C) can take so much time that it would be more productive to use OO C.
So you spend half a man hour renaming everything from .c to .cpp and compiling everything, casting any void pointers that the compiler may complain about. Is that half a man hour such a big price to pay for having language supported OOP at your disposal instead of doing it the hard way in pure C?
Argh!" I should have made myself clearer. I meant to say converting a C project to use C++'s fancy new features. If I were to add some polymorphic virtual abstract base classes and all that, I'd either have to write C++ wrappers for my C 'classes' (and hope that the compiler optimises it away), or convert any code that resembles what I posted previously in this thread to use a more C++ like approach ( = major rewrite). Or I could just hope that the new C++-ish stuff only interacts minimally with the existing code.
what's wrong with snakeskin leather?
It can't be cast into anything.
AE.
I'll pay you $100 to port Allegro to C++. As I'm generous I'll give you a whole day to do it
Reread his post. By his argument, Allegro is already C++. I mean, I've been using it with C++ for years ...
BTW, this should be common knowledge, but my goatee owns all your beards, reigning supreme on these forums for a year .... mua ha ha!
The problem with beards is there are too many ways of going about them, making them hard to maintain in the work environment. Plus, you have to rely on lowlevel methods of testosterone to produce proficient scruffs. Some people end up with mixed patches that just plain look ugly, not an impressing office factor.
Some/Most times the Nookie interface itself incurs huge costs all by itself.
My Nookie Provider suggested I apply the useGillette() method to her Nookie interface.
Some/Most times the Nookie interface itself incurs huge costs all by itself.
My Nookie Provider suggested I apply the useGillette() method to her Nookie interface.
That's a brave Provider you've got there, as the useGillette() method is generally considered "unsafe" as it does no bounds checking, and can actually damage the underlying hardware. Might I suggest a Wax pattern, and in particular the latest version coming out of Brazil.

Back on topic...
Lately I discovered that table-driven programming is a great 'alternative' to procedural or OOP programming. I used quotes around alternative because it can be used in a procedural or OOP environment.
I recently started to develop an asynchronous version of MooServer (server for a Multimedia Fusion plugin that allows online play) using Java. There are sockets, channels, connections, sessions, servers, players, etc. that can each be modelled with a class. So I started writing a class for each one, then the methods to make them interact. I actually found that all this OOP was getting in the way. My code was becoming spaghetti-like.
So I stepped back and thought, what would all this information look like in a relational database? So I designed some tables on paper and for the first time, I completely understood the relationships between all the data. So I coded everything in one class (MooServer) using tables to map all the data. The whole thing became so much simpler. The only reason I didn't finish this project (which would have taken about three full days) is that all this mundane life stuff came up that needed my attention - the same reason every project dies, but that's another story...
Here's a tiny snippet:
| 1 | package com.atulos.mooserver; |
| 2 | |
| 3 | import java.util.*; |
| 4 | |
| 5 | public class MooServer |
| 6 | { |
| 7 | private SetTable<Integer, Integer> connectionTable; |
| 8 | private SetTable<Integer, Integer> sessionTable; |
| 9 | private BidirectionalMap<Integer, String> sessionNaming; |
| 10 | private Hashtable<Integer, String> connectionNames; |
| 11 | private static int nextSessionId = 0; |
| 12 | |
| 13 | // Get the name of the connection |
| 14 | public String getConnectionName(int connectionId) |
| 15 | { |
| 16 | return connectionNames.get(connectionId); |
| 17 | } |
| 18 | |
| 19 | // Get the name of the session |
| 20 | public String getSessionName(int sessionId) |
| 21 | { |
| 22 | return sessionNaming.getRight(sessionId); |
| 23 | } |
The moral of the story is that if you have a clue about how to model information in a relational database and you have mapping data structures available, you should use OOP only to serve table-driven programming because table-driven programming absolutely rocks.
EDIT:
The problem with OOP is that, although it is nice for modelling individual types of real-world objects, there are no standards (besides is-a and has-a) for defining relationships between classes. It is left to the programmer to implement these relationships, without the opportunity to declare them in a standard way.
I suppose table-driven programming could be (and probably has been) implemented in plain old C quite effectively.
Reread his post. By his argument, Allegro is already C++. I mean, I've been using it with C++ for years ...
Not exactly. Allegro doesn't compile with C++ compiler and I understood that he meant making a C project compile as C++ one.
you should use OOP only to serve table-driven programming because table-driven programming absolutely rocks.
Your formulation of 'table driven programming' is a bit beardless, err weak. Real table oriented programming requires that the executable code also live in tables. That could be done in java or c# using dynamic class loading but I've not seen anyone do that.
I completely agree with you that oop is unsuited for many problems, for example my problem of easily creating a web application of 500 forms with simple to complex business logic. I think it was Paul Graham in on of his lisp articles who made the observation that business appiclations are basically a series of a arbitrary exceptions to general rules. Sure some things like customer management (name, address, account information) can be easily implemented in with oop or whatever, but when you get to bizarre stuff like handling the record keeping for variable rate annuities or tax regulations, oop falls flat on its face. Which is why in 2006 cobol is thriving.
C++, and here's why:
1) I find the code to be more readable. Done correctly, it's nigh impossible to not be able to easily locate the 'hooks' in your program.
2) I like my code to be as neat and structured as possible. The flexibility of a class far outweighs that of a struct when it comes to OOP.
3) It's more efficient in terms of time spent coding.
4) Reusability. I'm able to use many of my classes from program to program without having to make any changes to them at all.
5) They're fun!
Real table oriented programming requires that the executable code also live in tables.
I don't think table oriented/driven programming has been formalised to the extent that you can say what is real and what isn't, except that it should make heavy use of tables. My personal flavour of TDP involves storing all the data in tables and programming the relationships between them in a procedural manner. The Java collections API supports that rather nicely. To me, putting code in tables sounds like it could me a nice trick, but it would probably obstruct code readability and it seems like a way of using tables to achieve OOP (sounds like Lua).
That could be done in java or c# using dynamic class loading but I've not seen anyone do that.
Interestingly, I've done some dynamic class loading in Java. The purpose was to use Java as a scripting language in a Java MMORPG. I had it working so NPCs could be hot-swapped without changing their class names.
I suppose table-driven programming could be (and probably has been) implemented in plain old C quite effectively.
Here is a constructive critisism about OO and tables.
Well, its more of an individual likingness and comfortability factor with the two languages...
I like C++ over C and normally code only in C++ whenever I have to. It actually depends from a person to person...
Its not necessary for anyone of them them being better or superior but just a matter of choice...
Well, its just an opinion of mine and I might be wrong...
I'm still wondering what shared pointers has to do with beards.
However, the mystery that troubles me is why women in IT are so ugly. It's as if, in order to embrace technology you have to be a man or a minger.
I'm still wondering what shared pointers has to do with beards.
It's pretty simple, really. I have a beard and shared pointers don't. See how that works?
However, the mystery that troubles me is why women in IT are so ugly.
I'm curious as to why you think the men in IT aren't. Attractive people work in sales and marketing...
I use C with some extras provided by C++ (i.e. use of bools, and the STL library).
I've always programmed in a procedural way and am very happy with it!
I'm curious as to why you think the men in IT aren't. Attractive people work in sales and marketing...
I work in IT and (non-IT) women adore me. However I've seen Richard Phipps, which seems to correlate your statement
I work in IT and (non-IT) women adore me.
I almost choked on my dinner! 
Sniff.. I was having a bad hair day (or two) when those pictures were taken.
I work in IT and (non-IT) women adore me.
Your mom telling you how handsome you look in your tux on prom night doesn't count.
I work at a tech support center. Dunno if that counts as IT, but a lot of the more knowledgable girls on the floor are really cute.
Most of the guys are fat and ugly and we outnumber the girls 5 to 1; dunno how that fits into your theory though.
Pretty much confirms mine
And why anyone would want to use/have a weak_pointer<> is beyond me.
Ah, I miss that innocence
That is the bad thing about programming under Windows
Ah, I miss that innocence
Oh I love "technical" weak pointers, but I think a few people have missed the not so hidden joke
I work at a tech support center. Dunno if that counts as IT, but a lot of the more knowledgable girls on the floor are really cute.
Most of the guys are fat and ugly and we outnumber the girls 5 to 1; dunno how that fits into your theory though.
Wow. Where I work (also tech support), all the tech saavy women are simple technicians, and all the beautiful (but technically challenged) women have cushy overloard type supervisor jobs.
Anyways, back on topic. I prefer C++ because that was all we learned in college thus far (aside from JavaScript, Java, MySQL, and VB.NET).
more knowledgable girls on the floor are really cute.
Most of the guys are fat and ugly and we outnumber the girls 5 to 1; dunno how that fits into your theory though
Fits my theory: fat and ugly people think all girls are really cute.
However, the mystery that troubles me is why women in IT are so ugly. It's as if, in order to embrace technology you have to be a man or a minger.
Mayer?? Pssh... La plus belle "presentatrice" du monde est Mélissa Theuriau. A natural beauty and doesn't look like she has a plastic botoxed stretched face.
Voyez!
http://fresh99.com/images/frenchnewsanchor/M-Theuriau-0154.jpg
et
http://jfkaps01.free.fr/melissa_theuriau_041107b.jpg
et
http://liens-utiles.org/~jerry/melissa.jpg
et finalment
http://en.wikipedia.org/wiki/Melissa_Theuriau
You are missing the point Goalie: Melissa is a presenter, so they are chosen for their looks as well as their presenting skills. That Marissa seems to be a lecturer.
'That Marissa' is a Google VP.