OO, according to Alan Kay is all about message passing, and that's it. You will see that qualities such as polymorphism and encapsulation are actually derived from message passing.
Now that stance is in fact very extreme, because it basically means that only Smalltalk and languages alike would qualify.
I think you can define OO as building your system on entities, that fully encapsulate their state, and that are rendered exchangeable due to their inherent polymorphous qualities. One could thus argue a purely OO language ensures these two core qualities are always met. What renders OO languages "impure" would be mechanisms that allow the creation of constructs that do not meet these criteria, such as the possibilities to:
- declare public fields
- declare variables that can only hold instances of a specific class and its subclasses (i.e. variables should be typed against interfaces, which is what the biological objects communicate through in Kay's anology), which is rendered even narrower if the class in question is final, as that leaves even less room for polymorphism
- declare primitives
Then again, IMHO language purity is more a weakness than a strength. OO is not a silver bullet. No single paradigm is.
First, some rules of thumb:
Use std::unique_ptr
as a no-overhead smart pointer. You shouldn’t need to bother with raw pointers all that often. std::shared_ptr
is likewise unnecessary in most cases. A desire for shared ownership often betrays a lack of thought about ownership in the first place.
Use std::array
for static-length arrays and std::vector
for dynamic.
Use generic algorithms extensively, in particular:
<algorithm>
<numeric>
<iterator>
<functional>
Use auto
and decltype()
wherever they benefit readability. In particular, when you want to declare a thing, but of a type that you don’t care about such as an iterator or complex template type, use auto
. When you want to declare a thing in terms of the type of another thing, use decltype()
.
Make things type-safe when you can. When you have assertions that enforce invariants on a particular kind of thing, that logic can be centralised in a type. And this doesn’t necessarily make for any runtime overhead. It should also go without saying that C-style casts ((T)x
) should be avoided in favour of the more explicit (and searchable!) C++-style casts (e.g., static_cast
).
Finally, know how the rule of three:
- Destructor
- Copy constructor
- Assignment operator
Has become the rule of five with the addition of the move constructor and move assignment operator. And understand rvalue references in general and how to avoid copying.
C++ is a complex language, so it’s difficult to characterise how best to use all of it. But the practices of good C++ development haven’t changed fundamentally with C++11. You should still prefer memory-managed containers over manual memory management—smart pointers make it easy to efficiently do this.
I would say that modern C++ is indeed mostly free of manual memory management—the advantage to C++’s memory model is that it’s deterministic, not that it’s manual. Predictable deallocations make for more predictable performance.
As for a compiler, G++ and Clang are both competitive in terms of C++11 features, and rapidly catching up on their deficiencies. I don’t use Visual Studio, so I can speak neither for nor against it.
Finally, a note about std::for_each
: avoid it in general.
transform
, accumulate
, and erase
–remove_if
are good old functional map
, fold
, and filter
. But for_each
is more general, and therefore less meaningful—it doesn’t express any intent other than looping. Besides that, it’s used in the same situations as range-based for
, and is syntactically heavier, even when used point-free. Consider:
for (const auto i : container)
std::cout << i << '\n';
std::for_each(container.begin(), container.end(), [](int i) {
std::cout << i << '\n';
});
for (const auto i : container)
frobnicate(i);
std::for_each(container.begin(), container.end(), frobnicate);
Best Answer
C was never a subset of C++. The most obvious example of this is
int new;
. This has been true since C89 and C++98, and the languages have only grown further from each other as new standards have come out.Yes
A source file is written in one language or the other. A program can consist of code from multiple languages working together, or an executable produced by linking different compiled objects. You would say the program was written in C and C++, "C/C++" is not a language.
They never did.
char *a = malloc(10);
. C and C++ have never been fully compatible for at least as long as they've had ISO standards (I don't know all the details about the pre-standardized days). click the links or see below for a file that is fine with C89 and up, but isn't valid under any C++ standard.afaik no, but I don't know much about the C working group.
I always feel it's worth mentioning that C is a subset of Objective-C.