Szerkesztő:LinguisticMystic/cpp/StaticPolymorphism
🔁 Static Polymorphism in C++
[szerkesztés]In object-oriented programming (OOP), polymorphism is a foundational concept that increases code flexibility, reusability, and readability. Think of it as a Swiss Army knife: the same tool can perform different tasks based on how it’s used. Similarly, polymorphism lets you use the same function or operator in multiple contexts.
🎮 Real-Life Analogy
[szerkesztés]Imagine a character in a video game who can morph into different forms—each one useful in different situations. This is what polymorphism does in code: the same interface behaves differently depending on the context.
📚 Types of Polymorphism in C++
[szerkesztés]C++ supports two main types:
1. Static Polymorphism (Compile-Time)
[szerkesztés]- Decided before the program runs
- Achieved using:
- Function overloading
- Operator overloading
- Templates
2. Dynamic Polymorphism (Run-Time)
[szerkesztés]- Resolved during execution
- Achieved using:
- Virtual functions
- Inheritance
- Function overriding
🔁 Method Overloading (Static Polymorphism)
[szerkesztés]Function overloading allows multiple functions with the same name but different parameter types, numbers, or orders.
🖼 Example: Painter Class
[szerkesztés]#include <iostream>
class Painter {
public:
void draw() {
std::cout << "Drawing a circle." << std::endl;
}
void draw(int sides) {
std::cout << "Drawing a shape with " << sides << " sides." << std::endl;
}
void draw(int sides, const std::string& color) {
std::cout << "Drawing a " << color << " shape with " << sides << " sides." << std::endl;
}
};
int main() {
Painter picasso;
picasso.draw(); // Drawing a circle.
picasso.draw(3); // Drawing a shape with 3 sides.
picasso.draw(4, "red"); // Drawing a red shape with 4 sides.
return 0;
}
🔍 Explanation:
[szerkesztés]- All
drawfunctions are named the same. - The compiler distinguishes them by number and type of arguments.
⚙️ More Overloading Techniques
[szerkesztés]
1. By Parameter Type
[szerkesztés]class Geometry {
public:
double calculateArea(double radius) {
return 3.14159 * radius * radius;
}
int calculateArea(int side) {
return side * side;
}
};
📝 Here, the method performs different calculations based on the data type.
2. By Parameter Order
[szerkesztés]class UserProfile {
public:
std::string createProfile(std::string name, int age) {
return "Name: " + name + ", Age: " + std::to_string(age);
}
std::string createProfile(int age, std::string name) {
return "Age: " + std::to_string(age) + ", Name: " + name;
}
};
📝 The compiler selects the correct function based on the order of arguments.
🧰 Templates (Generic Programming)
[szerkesztés]Templates allow one function or class to operate with different types without rewriting code.
Example: Templated Adder Class
[szerkesztés]#include <iostream>
template <typename T>
class Adder {
public:
T add(T a, T b) {
return a + b;
}
};
int main() {
Adder<int> intAdder;
std::cout << intAdder.add(10, 20) << std::endl; // 30
Adder<float> floatAdder;
std::cout << floatAdder.add(10.5f, 20.3f) << std::endl; // 30.8
Adder<double> doubleAdder;
std::cout << doubleAdder.add(15.5, 25.5) << std::endl; // 41
return 0;
}
🧠 Why It Works:
[szerkesztés]- The compiler generates the correct version of
add()for each type. - This is compile-time polymorphism using generic programming.
🆚 Overloading vs Templates
[szerkesztés]| Feature | Method Overloading | Templates |
|---|---|---|
| Logic Control | Allows custom logic for each overload | Same logic applied to different types |
| Use Case | Behavior changes slightly with inputs | Generic operations on multiple types |
| Flexibility | Fixed types only | Type-agnostic (flexible, reusable) |
| Syntax | Multiple functions manually defined | Single templated function/class |
⚠️ Common Pitfalls
[szerkesztés]
❌ Overloading by Return Type Only
[szerkesztés]class Calculator {
public:
int sum(int a, int b) { return a + b; }
double sum(int a, int b) { return static_cast<double>(a + b); } // ❌ Error!
};
🔧 Return type alone is not sufficient for overloading—parameter list must differ.
❌ Ambiguity with Default Parameters
[szerkesztés]class VolumeController {
public:
void setLevel(int level) {}
void setLevel(int level, bool isMuted = false) {}
};
int main() {
VolumeController vol;
vol.setLevel(50); // ❌ Ambiguous: both overloads match
}
❗ Ambiguity arises when overloads differ only by default values.
❌ Overload Hiding in Inheritance
[szerkesztés]class Base {
public:
void play() { std::cout << "Base"; }
};
class Derived : public Base {
public:
void play(int volume) { std::cout << "Derived"; }
};
int main() {
Derived d;
// d.play(); ❌ Hidden by Derived::play(int)
d.Base::play(); // ✅ Calls Base::play
d.play(10); // ✅ Calls Derived::play
}
🔍 Inherited methods with the same name are hidden unless explicitly called using scope resolution.
✅ Best Practices
[szerkesztés]- Ensure distinct parameter signatures
- Avoid overloading by only return type
- Use default parameters carefully
- Be explicit with inheritance and
using Base::functionif needed - Document clearly which overloads exist and why
- Use templates for generic behavior, and overloading for fine-grained control
🧾 Conclusion
[szerkesztés]Static polymorphism in C++—through method overloading and templates—empowers developers to write versatile, type-safe, and clean code.
- Use method overloading when the logic differs based on arguments.
- Use templates when the logic is the same across different types.
- Understand the trade-offs and avoid common pitfalls like ambiguous signatures or hiding base methods.