Both Java and C++ are modern programming languages with native support for object oriented programming (OOP). While similar in syntax and features there are a bunch of differences in implementation and (default) behaviour which can be surprising for Java developers learning C++ or vice versa. In my post I will depict the basics of inheritance and polymorphism in C++ and stress the points Java developers may find surprising.
Basic inheritance or user defined types
Every Java programmer knows that all classes have java.lang.Object at the root of their inheritance hierarchy. This is not true for C++ classes: They do not share some common base class and do not inherit more or less useful methods like toString()
oder clone()
. C++ classes do not have any member functions besides the constructor and destructor by default. In Java all instance methods are virtual by default, meaning that if a subclass overrides a method from a superclass only the overridden version will be visible and callable on all instances of the subclass. We will see the different behaviour in the following example:
#include <iostream> #include <memory> using namespace std; class Parent { public: void myName() { cout << "Parent\n"; } virtual void morph() { cout << "Base class\n"; } }; class Child : public Parent { public: void myName() { cout << "Child\n"; } virtual void morph() { cout << "Child class\n"; } }; int main() { // initialisations more or less equivalent to // Parent parent = new Parent(); etc. in Java unique_ptr parent(new Parent); unique_ptr parentPointerToChild(new Child); unique_ptr child(new Child); parent->myName(); // prints Parent as expected parent->morph(); // prints Base class as expected parentPointerToChild->myName(); // surprise: prints Parent! parentPointerToChild->morph(); // prints Child class as expected child->myName(); // prints Child as expected child->morph(); // prints Child class as expected return 0; }
The difference to Java becomes visible in line 29 where we call to an instance of Child using the type Parent. Since myName() is not virtual the implementation in the parent class is not overridden but only shadowed by the subclass. Depending on the type of our variable on which we call the method either the parent method or the child method (line 31) is invoked.
Access modifiers in Java and C++ are almost identical as both are offering public
, protected
and private
. As there are no packages in C++ protected restricts access to child classes only.
Different syntax and fewer keywords
There are no keywords for interface or abstract class in C++ but the concepts are supported by pure virtual functions and multiple inheritance. So a class that defines a virtual function without a body like:
class Interface { public: virtual void m() = 0; };
becomes abstract and cannot be instanciated. Subclasses must provide implementations for all pure virtual functions or become abstract themselves. A class having exclusively pure virtual functions serves as the equivalent of an Java interface in C++. Since C++ supports inheritance from multiple classes you can easily use these features for interface segregation (see ISP). Most people advise against multiple implementation inheritance although C++ makes that possible, too.
Class interface control
One problem with inheritance in Java is that you always inherit all non-private methods of the base classes. This can lead to large and sometimes unfocused interfaces when using inheritance blindly. Delegation gives you more control about your classes interface and means less coupling but requires a bit more writing effort. While you can (and should most of the time) do the same in C++ it offers more control to your classes interface using private/protected inheritance where you can decide on an per-method-basis which functions to expose and what virtual functions you would like to override:
class ReuseMe { public: void somethingGreat(); void somethingSpecial(); }; // does expose somethingGreat() but hides sometingSpecial() class PrivateParent : private ReuseMe { public: using ReuseMe::somethingGreat; };
Children also gain access to their parents protected members.
Using super class functions and delegating constructors
Calling the functions of the parent class or other constructors looks a bit different in C++, as there is no super keyword and this is only a pointer to the current instance (please excuse the contrived example…):
class CoordinateSet { public: string toString() { stringstream s; std::copy(coordinates.begin(), coordinates.end(), std::ostream_iterator<double>(s, ",")); return s.str(); } protected: vector<double> coordinates; }; class Point : public CoordinateSet { public: // delegating constructor Point() : Point(0, 0) {} Point(double x, double y) { coordinates.push_back(x); coordinates.push_back(y); } // call a function of the parent class void print() { cout << CoordinateSet::toString() << "\n"; } };
I hope my little guide helps some Java people getting hold of C++ inheritance features and syntax.
Thanks for sharing this and its useful to know how to use polymorphism and inheritance in java…
Thank you for sharing this…its very useful for polymorphism and inheritance in java