OOP is successful in big project because it can offer the possibility to "prove" that a certain piece of code to do something "works" and it's immune from misinterpretations and abuse.
This is, of course, possible in most every language, but OOP seems to expose the basic concepts in a more direct way.
In languages like C, you can have a struct with functions doing "work" on them and, if use correctly, they work. The problem is that if you forget to call some "init" on your struct, or some "release" on your struct, or if you go there and change a value in that struct ignoring the fact that there are 3 more members that need to be changed to keep the struct in a "valid" state.
C++ (OOP in general) is an attempt to solve this by exposing objects with an interface that guarantee the validity of the data in every situation.
Now this seems to be the obvious way to go when writing programs in the large.. you see somebody's else class, you assume once you create it it'll be "ready to go" and that it'll be valid no matter what methods you call on it.
There goes the theory.. in practice, there seems to be a growing community of programmers that think that's not really the case.. and that all this bureaucracy in the languages is just moving the responsibilities around, from the user of the "black box" to the implementer of the "black box".. which sort of makes sense because the implementer should know better. But when there is a problem , then it is often hidden under countless layers of abstractions and constructs.
But in a perfect world, if you can choose between a mindset that goes:
// In C
// Instantiate a struct
MyStruct data;
// How I initialise this? Look for a function that looks like InitMyStruct.. found it
InitMyStruct(&data);
// Right, what can I do with this one? IDE can't help me, I have to guess a naming convention or potentially look in every possible .h
// for functions taking a MyStruct* as parameters.. ok got one
UpdateMember(&data);
// But... would this work too?
data.member=10;
// No way to know
// Now I am done with it... should I clean this up somehow? Start my endless search for something that looks like, cleanup, release, destroy.. you name it.
// Got it
ReleaseMyStruct(&data);
As opposed to the C++ "way":
MyClass c;
// No thinking, c is initialised and readu
// What can I do with this? Just write c. and get the IDE showing you the methods callable on c
c.UpdateMember();
// Can I do this?
c.member=10;
// If member is public, then it means it is possible to assume the member has no dependent members, so good to go
// Done with it? Should I worry about anything else? nope.. if there is clean up the destructor will take care of it
Why would you ever choose the C way?
Personally, I would feel "lost" in C after so many years of C++, but, I love coding in Google Go... and I really think that you guys in love with C should check Go out because reading your posts I had this feeling I was reading or listening to somebody of the Go team explaining the reasons behind the simplicity of Go and its relationship with C.
The mindset I have when using a Go library is totally different.. I dont rely on intellisense to suggest me the usage of a particular class, I open the implementation or the docs and read how to use it... as someone smarter than me put it: it looks like a polite conversation between engineers.. where, in C++ it often looks like the conversation between a paranoid father and a demented kid.