Soweit eigentlich kein Problem. Logging Klasse ist für loggen zuständig und Daemon Klasse fürs erzeugen eines Daemons (Linux).
Nun habe ich eine dritte Klasse die sowohl von Daemon als auch von Logging erben sollte. Da diese eigene Logeinträge erzeugen soll und daemonisiert werden soll.
Also:
class Application : public Daemon, private Logging
{
Application();
}
Und genau hier habe ich ein Problem. Da Logging nun zwei mal in Application da ist, ist es nicht mehr eindeutig welche log Funktion aufgerufen werden soll.
Mein Frage ist wie löse ich dieses Problem? (Ich habe keine Möglichkeite die Logging und Daemon Klassen zu ändern!)
Jedoch, ist dein Verschlag mit der virtuellen Vererbung keine Lösung des Problems.
Ich will nicht, dass Logging nur einmal an Applikation geerbt wird sonder sowohl für Applikation als auch an Daemon. (Da verschiedene Dateien zum Loggen genutzt werden z.B.).
Ich bin mittlerweile zu Schluss gekommen, dass hier keine Lösung durch Vererbung gibt. Natürlich ist die Lösung, ein Objekt in der jeweiligen Klassen an zu legen, möglich.
Sollte ich mich irren so belehrt mich gern eines Besseren!
Und genau hier habe ich ein Problem. Da Logging nun zwei mal in Application da ist, ist es nicht mehr eindeutig welche log Funktion aufgerufen werden soll.
Mein Frage ist wie löse ich dieses Problem? (Ich habe keine Möglichkeite die Logging und Daemon Klassen zu ändern!)
Zunächst mal kommst du an das log von Daemon grundsätzlich nicht mehr ran. Oder die private Vererbung ist ein Fehler in deinen Quellen.
Du müßtest Logging über eine weitere Zwischenklasse in Application reinholen - such mal nach dem Stichwort „Diamant“, falls du es noch nicht kennst - und dann über den Scoping-Operator das jeweils passende aufrufen. Das Ganze ist dann aber IMHO sehr unschön.
Hier mal ein vereinfachtes Beispiel:
_struct Logging {
Logging() {}
void log() {}
};
struct Daemon : public Logging {
Daemon() : Logging() {}
int daemonize() {return 0;}
};
struct Blah : public Logging {
};
class Application : public Blah, public Daemon {
Application();
};
Oder du benutzt, wie du selbst schon vorgeschlagen hast, eine Instanz von Logging innerhalb von Application. Für meinen Geschmack wäre das sauberer, aber ich kenne den Rest deines Programms nicht.
Ich habe es schon fast vermutet. Ich wollte eine Bestätigung haben. Die Lösung über eine zweite Klasse ist mir auch eingefallen. Nur halte ich diese (genau wie du) als nicht sauber. Ich werde das Problem mit einer Instanz von Logging im Daemon Klasse und in Applikations Klasse lösen. Ich denke es ist die sauberste Lösung.
um vielleicht eine andere Denkweise anzustoßen. Du solltest nicht von Logging erben, da der Zusammenhang ein „hat ein“ ist und nicht ein „ist ein“.
Am Besten legst du deine Loggingklasse als Singleton an, damit sie nur ein mal im gesamten Projekt verfügbar ist. Das geht so:
class Logging
{
private:
Logging(){/\*hier was initialisieren\*/};
public:
static Logging& getLoggingInstance()
{
static Logging singletonReference;
return singletonReference;
}
};
class Daemon
{
public:
Logging &myLog;
Daemon():myLog(Logging::getLoggingInstance())
{
}
};
Beachte, der Konstruktor von Logging ist private, damit kann man kein Objekt der Klasse direkt erstellen.
Was passiert hier:
beim ersten Aufrufen der statischen Methode getLoggingInstance() wird ein neues Objekt auf dem Stack konstruiert, hier funktioniert das, weil getLoggingInstance() ja ein teil der Klasse ist.
Da die Variable singletonReference als static deklariert ist, wird sie beim verlassen der Methode nicht wider zerstört, sondern bleibt über die gesamte Laufzeit erhalten.
Jedes mal wenn du jetzt getLoggingInstance() aufrufst bekommst du daher immer die gleiche Reference zurück und hast damit über das gesamt Programm so eine Art globale Klassenvariable^^.
Ich hoffe, die Erklärung reicht Dir, sonst gibts gerne mehr.