Classes get useful once you're tired of adding "this" pointers to all your "methods" and all the "this->" inside them...
Once a C program gets large enough, it seems to become rather "OO" naturally: there's going to be data grouped into structures, and code that operates on that data. That's what classes and methods are useful for. But you don't have to obsess over "forcing" your design to be OO, i.e. things like debating between A.foo(B) or B.foo(A), because sometimes foo(A,B) or even foo(A,B,C) is the answer.
I agree completely with the complexity argument --- and I'll add that hidden ("encapsulated", "abstracted", whatever you want to call it) complexity is still complexity that can get in the way of debugging and efficiency both in terms of machine and programmer time. The latter point is something that a lot of "modern C++" seems to miss, finding more complex ways to do simple things, which look simpler on the surface but are actually far more complex in total.
> Once a C program gets large enough, it seems to become rather "OO" naturally
Very well put. One of my current projects started in plain C but gradually evolved to the point that it just "became" a C++ project. Once you write the same code a few times in a few different places, it's blindingly obvious what would be would be less painful if represented as objects. And so on with other language constructs (inheritance, templates, etc.).
The main point I'm trying to get across is to let it happen naturally, instead of trying to force everything to become objects and methods. There will still be parts that are "not OO", but they are not OO because they don't need to be; and that's perfectly fine.
Once a C program gets large enough, it seems to become rather "OO" naturally: there's going to be data grouped into structures, and code that operates on that data. That's what classes and methods are useful for. But you don't have to obsess over "forcing" your design to be OO, i.e. things like debating between A.foo(B) or B.foo(A), because sometimes foo(A,B) or even foo(A,B,C) is the answer.
I agree completely with the complexity argument --- and I'll add that hidden ("encapsulated", "abstracted", whatever you want to call it) complexity is still complexity that can get in the way of debugging and efficiency both in terms of machine and programmer time. The latter point is something that a lot of "modern C++" seems to miss, finding more complex ways to do simple things, which look simpler on the surface but are actually far more complex in total.