1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
| #include <stdio.h>
typedef enum {
LoggerLevel_Error,
LoggerLevel_Warning,
LoggerLevel_Info,
LoggerLevel_Debug
} LoggerLevel;
/////////////////////////////////
// Object oriented programming //
/////////////////////////////////
// Base class
struct LoggerVTable;
typedef struct LoggerBase {
struct LoggerVTable* m_vtable;
} LoggerBase;
typedef struct LoggerVTable {
void(*m_log)(LoggerBase* self, const char* msg, LoggerLevel level);
} LoggerVTable;
void LoggerLog(LoggerBase* self, const char* msg, LoggerLevel level) {
self->m_vtable->m_log(self, msg, level);
}
// Derived class
typedef struct LoggerDeriv {
LoggerBase super;
FILE* m_file;
} LoggerDeriv;
void LoggerDerivLog(LoggerDeriv* self, const char* msg, LoggerLevel level) {
fprintf(self->m_file, "%s\n", msg);
}
void LoggerDerivLogWithCast(LoggerBase* self, const char* msg, LoggerLevel level) {
LoggerDerivLog((LoggerDeriv*) self, msg, level);
}
LoggerVTable loggerDerivVTable = { &LoggerDerivLogWithCast };
void LoggerDerivCtor(LoggerDeriv* self, FILE* file) {
self->super.m_vtable = &loggerDerivVTable;
self->m_file = file;
}
// Demo
void firstDemo() {
LoggerDeriv logger;
LoggerDerivCtor(&logger, stdout);
LoggerBase* loggerPtr = &logger.super;
LoggerLog(loggerPtr, "Object oriented programming.", LoggerLevel_Debug);
}
///////////////////////////////////
// Protocol oriented programming //
///////////////////////////////////
// Simple class
typedef struct SimpleLogger {
FILE* m_file;
} SimpleLogger;
void SimpleLoggerCtor(SimpleLogger* self, FILE* file) {
self->m_file = file;
}
void SimpleLoggerLog(SimpleLogger* self, const char* msg, LoggerLevel level) {
fprintf(self->m_file, "%s\n", msg);
}
// Protocol
typedef struct LoggerHandle {
void* m_obj;
void(*m_log)(void* obj, const char* msg, LoggerLevel level);
} LoggerHandle;
void LoggerHandleLog(LoggerHandle self, const char* msg, LoggerLevel level) {
self.m_log(self.m_obj, msg, level);
}
// Binding between SimpleLogger and LoggerHandle
void SimpleLoggerLogWithCast(void* self, const char* msg, LoggerLevel level) {
SimpleLoggerLog((SimpleLogger*) self, msg, level);
}
void LoggerHandleCtorSimpleLogger(LoggerHandle* self, SimpleLogger* obj) {
self->m_obj = (void*) obj;
self->m_log = &SimpleLoggerLogWithCast;
}
// Demo
void secondDemo() {
SimpleLogger logger;
SimpleLoggerCtor(&logger, stdout);
LoggerHandle loggerHandle;
LoggerHandleCtorSimpleLogger(&loggerHandle, &logger);
LoggerHandleLog(loggerHandle, "Protocol oriented programming.", LoggerLevel_Debug);
}
/////////////////////////
// Generic programming //
/////////////////////////
#define DefineSomeFunctions(loggerType) \
void loggerType ## LogTwice(loggerType* self, const char* msg, LoggerLevel level) { \
loggerType ## Log(self, msg, level); \
loggerType ## Log(self, msg, level); \
}
// Demo
DefineSomeFunctions(LoggerDeriv)
DefineSomeFunctions(SimpleLogger)
void thirdDemo() {
{
LoggerDeriv logger;
LoggerDerivCtor(&logger, stdout);
LoggerDerivLogTwice(&logger, "Generic programming with LoggerDeriv.", LoggerLevel_Debug);
}
{
SimpleLogger logger;
SimpleLoggerCtor(&logger, stdout);
SimpleLoggerLogTwice(&logger, "Generic programming with SimpleLogger.", LoggerLevel_Debug);
}
}
int main() {
firstDemo();
secondDemo();
thirdDemo();
return 0;
} |
Partager