#include <iostream>
#include <string>
#include <cmath>
using namespace std;

class Message
{
protected:
    string source;      //source of message
    string message;     //text in message

public:
    //constructor
    Message (const string& src, const string& msg) {
        source = src;      //initialize source
        message = msg;     //initialize message
    }

    //convert message to string
    virtual string getMessage() const {
        return source + ": " + message;
    }
};

class ErrorMessage : public Message
{
protected:
    string errorCode;         //error messages have error codes

public:
    //constructor
    ErrorMessage(const string& ec, const string& src, const string& msg)
    : Message (src, msg) {
        errorCode = ec;         //initialize error code
    }

    //convert message to string
    virtual string getMessage() const {
        return "ERROR " + errorCode + ": " + source + ": " + message;
    }
};


ostream& operator << (ostream& os, const Message& msg) {
    return os << msg.getMessage();
}

int main () {

    cout << Message ("main", "Test message") << endl;
    Message msg2 ("main", "Test message 2");
    cout << msg2.getMessage() << endl;
    ErrorMessage error ("1234", "Hard drive", "Out of space");
    cout << error << endl;

    return 0;
}

