I have must have learned at least a dozen programming languages in my time, and none was as difficult and as counter-intuitive as C++. (Compared to C++, Ada was simple.) I think C++ was just a bad idea, a clumsy attempt to merge two incompatible paradigms.
In classical imperative programming (e.g. C, Algol, Fortran, Pascal, and Basic), procedures contain and copy data structures. The heap primarily exists when unusual flexibility is needed, e.g. when the number of data objects you need isn't known until runtime. so you manage them with a global heap-based collection. Generally, you try to avoid using the heap, and where you must use it, you build an API around your collection to hide the nasty ugly details.
Compared with imperative programming, object orientation provides a kind of inversion of control. Instead of having procedures which contain and manipulate data structures, you have objects which contain methods (to handle the messages that other objects send it). Objects manage their own lifecycles and storage allocation. This sort of distributed control implies a level of abstraction well above concerns about storage management. Instances of subclasses tend to be larger than instances of their parent classes, but so users of these polymorphic objects are presumed to be above worrying about the storage they take up. But that makes us dependent upon that nasty heap -- is it any wonder that the vast majority of object oriented languages _presume_ automatic garbage collection?
The very fact that the C++ programmer is responsible for storage management implies that C++ objects are not to be visualized as independent and cooperating entities that manage their own lifecycles -- because then it becomes unclear as to who will have responsibility for cleaning up.
Systems programming is of necessity low-level; a reliance upon automatic garbage collection simply isn't appropriate for those kinds of problems. Therefore, instead of trying to add object orientation to C (and therefore an over-reliance upon the heap), I think we'd have been better off to begin by simply adding a strong, polymorphic type system. Then we could write systems programs with a manageable degree of genericity, without requiring every programmer to become a language-lawyer interpeting seemingly conflicting regulations, or an empirical scientist running experiments to determine what his programming language does in a given situation.
If we could then create easy hooks by which an object-oriented language could make calls to low-level subroutines written in that systems programming language, so much the better.
In classical imperative programming (e.g. C, Algol, Fortran, Pascal, and Basic), procedures contain and copy data structures. The heap primarily exists when unusual flexibility is needed, e.g. when the number of data objects you need isn't known until runtime. so you manage them with a global heap-based collection. Generally, you try to avoid using the heap, and where you must use it, you build an API around your collection to hide the nasty ugly details.
Compared with imperative programming, object orientation provides a kind of inversion of control. Instead of having procedures which contain and manipulate data structures, you have objects which contain methods (to handle the messages that other objects send it). Objects manage their own lifecycles and storage allocation. This sort of distributed control implies a level of abstraction well above concerns about storage management. Instances of subclasses tend to be larger than instances of their parent classes, but so users of these polymorphic objects are presumed to be above worrying about the storage they take up. But that makes us dependent upon that nasty heap -- is it any wonder that the vast majority of object oriented languages _presume_ automatic garbage collection?
The very fact that the C++ programmer is responsible for storage management implies that C++ objects are not to be visualized as independent and cooperating entities that manage their own lifecycles -- because then it becomes unclear as to who will have responsibility for cleaning up.
Systems programming is of necessity low-level; a reliance upon automatic garbage collection simply isn't appropriate for those kinds of problems. Therefore, instead of trying to add object orientation to C (and therefore an over-reliance upon the heap), I think we'd have been better off to begin by simply adding a strong, polymorphic type system. Then we could write systems programs with a manageable degree of genericity, without requiring every programmer to become a language-lawyer interpeting seemingly conflicting regulations, or an empirical scientist running experiments to determine what his programming language does in a given situation.
If we could then create easy hooks by which an object-oriented language could make calls to low-level subroutines written in that systems programming language, so much the better.