polymorphism

polymorphism:
providing a single interface to entities of different types

There are no polymorphic types, only a polymorphic use of similar types

types of polymorphism in C++

  • Compile-time
    • Overloaded functions
    • Templates
  • Run-time
    • Virtual functions
  • ​External
int main()
{
    auto a = 1 + 2;
    auto b = 1.0 + 2.0;
    auto c = 1l + 2.f;

    return a + b + c;
}
#include <iostream>

void fun(int) {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
}

void fun(double) {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
}

int main() {
    fun(1);
    fun(2.0);
}
#include <iostream>

template <typename T>
void fun(T arg)
{
    std::cout << arg << " :: " 
              << __PRETTY_FUNCTION__ 
              << std::endl;
}

int main() {
    fun(1);
    fun(2.0);
}
#include <iostream>

struct Interface {
    virtual ~Interface() = default;
    virtual void fun() = 0;
};

struct C1 : public Interface {
    ~C1() override {}
    void fun() override { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};

struct C2 : public Interface {
    void fun() override { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};

void fun(Interface& i) { i.fun(); }

int main() {
    C1 c1;
    C2 c2;

    fun(c1);
    fun(c2);
}
#include <iostream>
#include <string>

struct Logger {
    virtual void log(std::string msg) = 0;
};

struct StdLogger : public Logger {
    void log(std::string msg) override { std::cout << "stdlog :: " << msg << std::endl; };
};

struct Worker {
    Worker(Logger& l) : logger(l) {}
    void run(){ /* lots of calculations */ logger.log("hello");}
private:    
    Logger& logger;
};

int main() {
    StdLogger log;
    Worker w1(log);
    w1.run(); // this should print to std::cout

//    Worker w2();
//    w2.run(); // this should print to file
}
#include <iostream>
#include <string>
#include <functional>

struct Worker {
    Worker(std::function<void(std::string)> f) 
    : log(f) {}

    void run(){ log("hello"); }
private:
    std::function<void(std::string)> log;
};

int main() {

    Worker w1([](auto m) {std::cout << "lambda ::" << m << std::endl;});
    w1.run(); // this should print to std::cout

//    Worker w2;
//    w2.run(); // this should print to file

}
#include <iostream>
#include <string>

struct StdLogger {
    void log(std::string msg) { std::cout << "stdlog :: " << msg << std::endl; };
};

struct FileLogger {
    void log(std::string msg) { std::cout << "filelog :: " << msg << std::endl; };
};

struct Worker {
    template <typename Logger>
    Worker(Logger& l) : logger(&l)
    , log{[](void* p, std::string m) { static_cast<Logger*>(p)->log(m); }} {}

    void run(){ /* lots of calculations */ log(logger, "hello");}
private:
    void* logger;
    void (*log)(void*, std::string);
};

int main() {
    StdLogger log;
    Worker w1(log);
    w1.run(); // this should print to std::cout

    FileLogger log2;
    Worker w2(log2);
    w2.run(); // this should print to file
}
// I will add example about concept-based polymorphism

deck

By Filip Sajdak