Lesson 3
Polymorphism in C++ for Backward Compatibility
Introduction

Hello, learner! In today's exciting chapter, we will explore Polymorphism, a prominent feature of Object-Oriented Programming (OOP). Specifically, we will study its role in maintaining backward compatibility while introducing new features. Think of it as a software update that introduces new functions without breaking the older functionality — ingenious, isn't it?

Understanding Polymorphism

Polymorphism, a principle that derives from the Greek words 'poly' (many) and 'morphism' (forms), enables a function or class in C++ to handle different types and forms. In C++, polymorphism is often achieved through the use of virtual functions and method overriding.

Consider a base class Bird with a virtual method fly(). If we create derived classes like Sparrow, Penguin, and Ostrich, we can override the fly() method for certain subclasses. This demonstrates polymorphism in action.

C++
1#include <iostream> 2using namespace std; 3 4class Bird { // Base class 5public: 6 virtual string canFly() { 7 return "Unknown"; 8 } 9}; 10 11class Sparrow : public Bird { // Derived class 12public: 13 string canFly() override { 14 return "Yes, I can fly!"; 15 } 16}; 17 18class Penguin : public Bird { // Derived class 19public: 20 string canFly() override { 21 return "No, I prefer swimming."; 22 } 23}; 24 25int main() { 26 Sparrow sparrow; 27 Penguin penguin; 28 cout << "Sparrow says: " << sparrow.canFly() << endl; // Output: "Yes, I can fly!" 29 cout << "Penguin says: " << penguin.canFly() << endl; // Output: "No, I prefer swimming." 30 return 0; 31}
Polymorphism for Backward Compatibility

When adding new features that introduce new behaviors to some components, polymorphism ensures that the existing parts function as before, thereby retaining backward compatibility. C++ achieves this through virtual functions and method overloading.

For example, consider a MathOperations class with a multiply() method that accepts two parameters. To support the multiplication of three numbers, create an ExtendedMathOperations class that inherits from MathOperations and includes a new multiply() method.

C++
1#include <iostream> 2using namespace std; 3 4class MathOperations { // Base class 5public: 6 virtual int multiply(int a, int b) { 7 return a * b; 8 } 9}; 10 11class ExtendedMathOperations : public MathOperations { // Derived class 12public: 13 int multiply(int a, int b) override { 14 return MathOperations::multiply(a, b); // Call the base class version 15 } 16 17 int multiply(int a, int b, int c) { 18 return a * b * c; 19 } 20}; 21 22int main() { 23 MathOperations mathOps; 24 ExtendedMathOperations extendedMathOps; 25 cout << mathOps.multiply(2, 3) << endl; // Output: 6 26 cout << extendedMathOps.multiply(2, 3) << endl; // Output: 6, keeping backward compatibility 27 cout << extendedMathOps.multiply(2, 3, 4) << endl; // Output: 24 28 return 0; 29}
Real-Life Examples

Consider a Document class that prints a text document and a derived class PhotoDocument that supports color prints as an example. This design allows the implementation without changing Document::printDoc().

C++
1#include <iostream> 2using namespace std; 3 4class Document { 5protected: 6 string text; 7public: 8 Document(string t) : text(t) {} 9 10 virtual void printDoc() { 11 cout << "Printing document: " << text << endl; 12 } 13}; 14 15class PhotoDocument : public Document { 16public: 17 PhotoDocument(string t) : Document(t) {} 18 19 void printDoc(bool isColorPrint = false) { 20 string printType = isColorPrint ? "Colour " : ""; 21 cout << printType << "Printing document: " << text << endl; 22 } 23}; 24 25int main() { 26 Document doc("Hello"); 27 doc.printDoc(); // Output: Printing document: Hello 28 29 PhotoDocument photoDoc("Beautiful Sunset!"); 30 photoDoc.printDoc(); // Output: Printing document: Beautiful Sunset! 31 photoDoc.printDoc(true); // Output: Colour Printing document: Beautiful Sunset! 32 33 return 0; 34}
Pros and Cons of Using Polymorphism for Backward Compatibility

As with any programming approach, using polymorphism to maintain backward compatibility comes with its own set of advantages and disadvantages. Here, we will explore two key pros and two cons to give you a more balanced understanding.

Pros

  1. Flexibility in Feature Expansion: Polymorphism allows for easy extension and addition of new features without altering the existing system's functionality. This means developers can introduce new derived classes that provide enhanced features while the original classes remain unaffected and continue to support legacy systems.

  2. Seamless Integration with Existing Codebase: Since polymorphism enables new features to coexist with older ones through subclassing, integrating these features into the existing codebase does not disrupt the functionality of legacy systems. This approach minimizes the risk of breaking changes and ensures a smoother transition for systems adopting new features.

Cons

  1. Increased Complexity: While polymorphism promotes flexibility and integration, it can also lead to a more complex codebase. Developers must understand the entire hierarchy and the relationships between classes to effectively implement and maintain the system. This complexity might slow down development and increase the likelihood of errors.

  2. Potential Overhead in Performance: The use of polymorphism, especially when it involves a deep class hierarchy or extensive method overriding, might introduce runtime overhead. This is because the program needs to determine the correct method to execute at runtime dynamically, which could impact performance, particularly in systems where efficiency is critical.

Understanding these pros and cons is essential for making informed decisions when considering polymorphism as a strategy for adding new features while keeping backward compatibility.

Lesson Summary and Practice

You have aced the understanding of Polymorphism and its role in maintaining backward compatibility. Now, gear up for insightful exercises to reinforce today's learning. Regular application is the key to mastering these concepts. Are you ready to put your skills to the test? Let's go!

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.