Mehrfachvererbung Problem

Hallo Leute,

ich habe ein Problem mit mehrfach Vererbung. Folgendes ist gegeben:

class Logging
{
public:
Logging(string name);

void log(string text);
}

class Daemon :stuck_out_tongue:rivate Logging
{
Daemon(string appName);

int daemonize();
}

Daemon::smiley:aemon(string appName)
Logging(„daemon obj“)
{

}

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();
}

Application::Application()
:Logging(„Application obj“), Daemon(„XYZ“)
{

log(„constructor“);
}

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!)

Danke im Voraus!

Gruß

Andreas

PS: Ich kompiliere mit dem g++

[MOD]: Schreibfehler in Titel verbessert

Howdy,

so lese er

http://www.cprogramming.com/tutorial/virtual_inherit…

zum Thema public virtual in C++.

Gruss
Norsemanna

Hallo und danke für die Antwort.

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!

Gruß

Andreas

Hallo!

[Quelltext]

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.

Zur eigentlichen Frage: In der derzeitigen Vererbungshierarchie geht das gar nicht. Ich hatte selbst vor einiger Zeit dieses Problem (siehe /t/zugriff-auf-basisklasse-bei-mehrfachvererbung/603…

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();
};

Application::Application() : Blah(), Daemon() {
Blah::log();
Daemon::log();
}_

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.

Gruß, Jan.

Danke!!!

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.

Vielen Dank noch mal für die Antwort!

Gruß

Andreas

Hallo,

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.

Grüße

Ach mist. Ich sollte mir mal angewöhnen den Text komplett zu lesen.

Vergiss den Kram, der oben steht.

Auf die Member der Loggingklasse kannst du mit Logging::Log(„bla bla“) zugreifen. Du solltest es jedoch nicht private vererben, sondern public.

Grüße