(Let’s be brief, incomplete…Page numbers refer to [[C# precisely]] )
— fundamental differences among the myriad differences
Diff — delegates, events, lambda – expanded C++ stateless functor
Diff — non-virtual method? counter-intuitive to both C++ and java guys,
diff: enums. Fundamentally different. A Java enum type is a “singleton” class.
Diff — generics
Diff — expression tree
–fundamental but less exploited
Diff — ref param, out param
** assignment to a method param are visible to caller method ! P71
Diff — hiding rule — less clean than java. Even more complicated than C++ hiding rules
** you can even hide a virtual method! P 75
Diff: struct? a “kernel” innovation but unimportant in “userland”. P54
Diff: simple (i.e. primitive) types are aliases of struct types. Replaces autoboxing. Fundamentally they are same as java primitives
Diff: operator overloading like ==. Similar to equals() override in J
diff: access modifiers “internal”, default. Similar to “package access” in J
diff: Integration of primitive and wrapper classes into structs — primitive wrappers glorified
diff: simple types having methods.
–higher-level or local/peripheral features
diff: explicit interface members
class properties and indexers? accessors glorified
implicit user-defined type conversions? tricky and not widely used
IDisposable/using — “finally” glorified
rectangular/jagged arrays? Only one of them is widely used.
all nested classes are all static
c++ has (non-trivial) hiding rules for member functions AND free functions …. See P37 / P236 [[effC++]].
I feel c++ method hiding is best studied along with overriding/overloading. See http://bigblog.tanbin.com/2011/12/hiding-redefining-overriding.html
For other forms of hiding, see my blog posts http://bigblog.tanbin.com/search/label/c%2B%2Bc%23java_hiding
Within an inheritance hierarchy, Java supports static method hiding; C# uses “new” to make hiding explicit.
I consider overloading and overriding 2 magic tricks by the compiler. Here are a few contrasts as far as I can see.
Example of overloading —
– Overloading is compile-time magic; overriding is run-time magic. If you have a D object’s address in a variable myVar and you pass it function1, which function1 is chosen by compiler? Depends on the declared type of myVar. Discussed repeatedly in my blog.
– consider renaming to function1_for_Base()/function1_for_Derived() etc. It may seem cool to have a bunch of overload functions, but in one Barcap email sender utility class, there are 4 send(…) utilities each with more than 7 parameters — code smell. It’s hard for users to tell them apart. P403 [[c++TimesavingTechniques]] points out that overloading complicates debugging and maintenance.
** Readability is fine in overRiding
– Overriding is generally a best practice to be adopted whenever possible. I can’t say the same about overloading.
– c++ has hiding rule about overLoading. No such thing about overRiding.
– c++ does implicit (!) type conversion about overLoading.
– In conclusion, overriding is cleaner than overloading, less complicated, and more readable.
– In overriding There’s more magic by compiler — vptr etc. More powerful but Not more complicated
– overLoad can be applied to operators such as op=, op+. I doubt overRide can
(c# has the trickiest hiding rules; c++ has more than java.)
First, remember the onion model described in other posts. To rephrase one more time, each instance field occupies memory “cells” in a layer of the onion. If class B has an instance field vf, and subclass C has a same-name instance field vf, then a C “onion” has storage for both fields.
myRef.vf resolves to one of the 2 fields at compile time depending on declared type of myRef. P40 [[java precisely]]
On P25 [[java precisely]], B has a static field sf, and so does C. The C onion in memory has NO storage for either field, but it has a pointer to the class object, which has storage for the field.
Q: does the C class object have storage for both static fields?
%%A: probably no. C class object just needs a pointer to B class object.
Question: “myRef.sf” refers to …? P40 [[java precisely]]
A: At compile time, if the C onion is declared as type B, then the field is B.sf
A: At compile time, if the C onion is declared as type C, then the field is C.sf
I feel the static and non-static cases are similar — both compile-time binding. This is the simple rule for field binding. For method call binding, static and non-static behave differently. Remember that runtime binding is very strict and requires non-static and non-field, among other conditions. Failing any condition means compile-time binding.
I’m sure there are excellent online articles, but here’s my own learning note.
Java “new” always hits Heap, period. Simple and clean.
C++ has array-new, placement-new, and class-specific-new. C++ “new” almost always hits the heap except
– except placement-new
– except you can customize op-new for your class to hit your allocator.
C# “new” doesn’t always mean Heap. The code “new MyStruct” usually hits the stack rather than the heap. See P55[[c#precisely]] for a nice diagram.
C# actually gives 3 unrelated (mildly confusion) meanings to the “new” keyword. One is the Java meaning. The 2nd meaning is “hide base type Member” and can apply to
* virtual methods — Most confusing
* non-virtual methods
* nested classes/interfaces
“Type” can be a base interface.
3rd meaning – select-new creates an instance of an anonymous type . See http://www.dotnetperls.com/select-new. http://stackoverflow.com/questions/2263242/select-new-keyword-combination is a summary of select-new
 java also let’s you create an instance of an anonymous type but you need to specify the supertype.
[[Java precisely]] P40 summarizes
· In a non-static field access o.f, the field referred to is determined by the compile-time type of the object expression o
· In a non-static call to a non-private method o.m(), the method called is determined by the run-time class of the target object: the object to which o evaluates to
Say C.java extends B.java,
Q: if you only have an object o=new C(), how can you access f and m() declared in B.java?
A: With the exception below, you can’t access B::m(). The method call o.m() resolves at run time and always binds to C::m(). However, f is a different story. You can cast o to B and o.f would refer to B::f
A special context — super.f and super.m() do give you access to parent’s members, but you can only use this syntax in C’s constructors or non-static methods, essentially in C.java source code.
I wonder what C++ does.. Here are some tidbits.
o.B::m() actually let’s you call parent’s m() via a subclass object. Also see Item 50 in [[eff c++]]