template-klasse member übergeben



  • hallo

    ein stück code sagt mehr als 1000 worte:

    template<class T, T *parent>
    struct base
    {
    	virtual ~base()
    	{
    		delete parent;
    	}
    };
    struct test : public base<int, test::ptr>
    {
    	test()
    	{
    		ptr = new int;
    	}
    	int *ptr;
    };
    

    ich will im prinzip erreichen dass die basisklasse meinen zeiger aus der abgeleiteten klasse löscht. durch erben soll ein destruktorcode automatisch
    ausgeführt werden, die basissklasse kennt jedoch nicht alle verschiedenen
    löschroutinen.

    geht das?



  • Nein,

    Destruktoren können nicht aufgerufen werden



  • vermutlich hab ich mich unverständlich ausgedrückt 🙂

    klasse A kann mehrere objekte der klasse B erzeugen. sobald ein objekt der
    klasse B gelöscht wird, meldet es sich von der oberklasse A ab, die in einer
    liste die kindobjekte verwaltet.

    void B::~B()
    {
        // parent vom typ A*
        // typedef std::vector<B *> vec;
        vec &v = parent->childs;
    
        for (vec::iterator i = v.begin(), end = v.end(); i != end; ++i)
        {
            if (*i == this)
            {
                v.erase(i);
                break;
            }
        }
    }
    

    es geht nur darum nicht in jedem destruktor (mittlerweile ziemlich viele)
    so einen aufräumcode zu schreiben.

    deshalb soll das eine andere klasse in ihrem destruktor machen, von der ich dann
    erben kann. fertig ist das ganze. nur wie kommt die basisklasse an den
    benötigten zeiger? konstruktor wäre eine möglichkeit, aber geht das wirklich
    nicht über die template-parameter-liste ?



  • Also für so etwas sollte Vererbung nicht eingesetzt werden.. Das wäre Designtechnischer Unsinn. (Obwohl es irgendwie klingt, dass du da sonst noch ein Problem hast, wo Vererbung sinnvoll eingesetzt werden könnte.. Anscheinend haben die "vielen" Klassen ja eine Gemeinsamkeit und genau das solltest du auslagern und nicht nur irgendwie probieren das aufräumen übernehmen zu lassen)

    Ansonten mach lieber eine Funktion, die das dann für dich übernimmt und die rufst du dann einfach im dtor auf und übergibst die nötigen Variablen.



  • sie haben keine gemeinsamkeit, allerdings kann die eine klasse durch die andere erzeugt werden.

    warum darf man da nicht vererbung einsetzen? ich erbe halt von einer aufräum-klasse.


  • Administrator

    daersc schrieb:

    Destruktoren können nicht aufgerufen werden

    Doch können sie, nur sollte man da wissen, was man tut 😉

    @vorlage,
    Templateparameter müssen zur Kompilezeit bekannt sein. Dein test::ptr ist allerdings erst zur Laufzeit bekannt, daher geht dies nicht.

    Für dein Problem würde ich aber auch eher eine freie Funktion verwenden. Vielleicht diese mit Templateparameter versehen, damit sie für unterschiedliche Typen funktioniert. Und dann eben immer einen Funktionsaufruf in den jeweiligen Destruktor.
    Aber wie die genau auszusehen hat, da müsstest du nochmals ein wenig genauer erklären, was du machst 🙂

    Grüssli



  • vorlage schrieb:

    warum darf man da nicht vererbung einsetzen? ich erbe halt von einer aufräum-klasse.

    Dürfen schon, aber das ist nicht der Sinn von Vererbung. Vererbung wird dort eingesetzt, wo Zusammenhänge und Gemeinsamkeiten dargestellt werden sollen und nicht die Schreibfaulheit unterstützen. Das würde zusätzlich die ganze Hierarchie komplizierter machen, als das sie ist. Eine freie Funktion ist dafür besser geeignet, da du da in etwa den gleichen Schreibaufwand hast (ein Funktionsaufruf im dtor, anstatt die Vererbung), allerdings ist die Hierarchie nicht gestört und das gesamte einfacher zu verstehen.
    Stell dir dazu mal vor, dass jemand anders, als du die Klasse anschaut und wenn er da eine Ableitung sieht, wird er die zuerst nicht anschauen, sondern schaut mal, was die Klasse so macht und wird feststellen, dass da irgendwie Speicher nicht aufgeräumt wird und im dtor findet er dann auch nichts. Bis er schlussendlich auf die wahnsinnige Idee kommt in der Basisklasse zu suchen. - Das ist doch verwirrend, nicht? - Im Gegensatz dazu ist alles klar, wenn im dtor eine Funktion aufgerufen wird und der diese gewissen Ressourcen übergeben werden. Einfach, klar und verständlich.



  • vorlage schrieb:

    void B::~B()
    {
        // parent vom typ A*
        // typedef std::vector<B *> vec;
        vec &v = parent->childs;
    
        for (vec::iterator i = v.begin(), end = v.end(); i != end; ++i)
        {
            if (*i == this)
            {
                v.erase(i);
                break;
            }
        }
    }
    

    die schleife muß natürlich in die besitzerklasse rein.

    class Hund;
    class Besitzer
       vector<Hund*> hunde;
    ...
       viud fuegeHundHinzu(Hund* h){
          hunde.push_back(h);
       }
       void entferneHund(Hund* h){
          //hier die schleife
       }
       ~Besitzer(){
          //assert(hunde.empty());
       }
    };
    class Hund{
       Besitzer besitzer;
       Hund(Besizer* besizter){
          this->besitzer=besitzer;
          besitzer->fuegeHundHinzu(this);
       }
       virtuel ~Hund(){
          besitzer->entferneHund(this);
       }
       private: operator=(Hund const&);
    };
    

    das versprechen, daß hunde immer einen besitzer haben und sich beim sterben brav abmelden, kann man schon in die basisklasse stopfen. da sehe ich kein problem.
    mir scheint, in der ursprünglichen frage wurden nur besitzdinge und vererbungsdinge vermischt.


Anmelden zum Antworten