Solution: Singleton (Flexible)

Main Program

#include "social-insurance-svs.h"
#include "social-insurance-oegk.h"

#include <iostream>
#include <string>
#include <memory>


int main()
{
    // setup phase, next to program startup
    SocialInsurance::set_instance(std::make_unique<SVS>());

    std::string id("1037190666");

    SocialInsurance::instance().charge(id, 1254.60);
    SocialInsurance::instance().charge(id, 231.34);
    
    std::cout << id << " owes \"" << SocialInsurance::instance().name() << "\" " << SocialInsurance::instance().debt(id) << " Euros" << std::endl;

    // can only be a runtime error: trying to overwrite singleton
    // instance
    SocialInsurance::set_instance(std::make_unique<OEGK>());

    return 0;
}

SocialInsurance Interface

#pragma once

#include <memory>


class SocialInsurance
{
public:
    const std::string& name() const { return _name; }

    virtual void charge(const std::string& id, double euros) = 0;
    virtual double debt(const std::string& id) const = 0;

private:
    std::string _name;

public:
    static void set_instance(std::unique_ptr<SocialInsurance>);
    static SocialInsurance& instance();

protected:
    SocialInsurance(const std::string& name) : _name(name) {}

private:
    static std::unique_ptr<SocialInsurance> _instance;
};
#include "social-insurance-flexible.h"

#include <stdexcept>


std::unique_ptr<SocialInsurance> SocialInsurance::_instance;

SocialInsurance& SocialInsurance::instance()
{
    if (_instance == nullptr)
        throw std::runtime_error("SocialInsurance singleton not in place");
    return *_instance;
}

void SocialInsurance::set_instance(std::unique_ptr<SocialInsurance> obj)
{
    if (_instance != nullptr)
        throw std::runtime_error("SocialInsurance singleton already in place");
    _instance = std::move(obj);
}

Two Concrete Implementations

OEGK

#pragma once

#include "social-insurance-flexible.h"

#include <iostream>
#include <map>


class OEGK : public SocialInsurance
{
public:
    OEGK() : SocialInsurance("OEGK") {}

    virtual void charge(const std::string& id, double euros);
    virtual double debt(const std::string& id) const;

private:
    std::map<std::string, double> _database;
};
#include "social-insurance-oegk.h"


void OEGK::charge(const std::string& id, double euros)
{
    _database[id] += euros;
}

double OEGK::debt(const std::string& id) const
{
    auto found = _database.find(id);
    if (found == _database.end())
        throw std::runtime_error("not found");
    return found->second;
}

SVS

#pragma once

#include "social-insurance-flexible.h"

#include <iostream>
#include <map>


class SVS : public SocialInsurance
{
public:
    SVS() : SocialInsurance("SVS") {}

    virtual void charge(const std::string& id, double euros);
    virtual double debt(const std::string& id) const;

private:
    std::map<std::string, double> _database;
};
#include "social-insurance-svs.h"


void SVS::charge(const std::string& id, double euros)
{
    _database[id] += euros * (110.0L / 100);
}

double SVS::debt(const std::string& id) const
{
    auto found = _database.find(id);
    if (found == _database.end())
        throw std::runtime_error("not found");
    return found->second;
}