Ugrás a tartalomhoz

Szerkesztő:LinguisticMystic/cpp/StaticPolymorphism

A Wikiszótárból, a nyitott szótárból

🔁 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 draw functions 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::function if 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.