Funktion für die Nutzung der Methode ToString() in verschiedenen Klassen.



  • Moin,

    ich möchte eine Funktion schreiben, welche allgemein von Klassen die ToString Funktion nutzt. Es gibt also Klassen C1, C2, C3, etc. welche eine Funktion ToString() definiert haben und wie folgt definiert sind:

    class C1{
    private:
        std::string NameVar;
    /*Der Rest der Klasse ist stets unterschiedlich*/
    public:
        std::string ToString(){return NameVar;}
        void DefineName(const std::string fName, void* objArr, int nObj){this->NameVar = GetNextName(fName, objArr, nObj);}
    /*Der Rest der Klasse ist stets unterschiedlich*/
    }
    
    class C2{
    private:
        std::string NameVar;
    /*Der Rest der Klasse ist stets unterschiedlich*/
    public:
        std::string ToString(){return NameVar;}
        void DefineName(const std::string fName, void* objArr, int nObj){this->NameVar = GetNextName(fName, objArr, nObj);}
    /*Der Rest der Klasse ist stets unterschiedlich*/
    }
    

    Ich habe dann einen Stapel mit diesen Objekten. Es gibt also einen Stapel für C1, einen für C2 usw.
    Ich möchte vermeiden, dass zwei Objekte in diesem Stapel den gleichen Namen haben. Wenn ein bereits
    vorhandener Name gewählt wird, soll dieser automatisch durch <Name_001> ersetzt werden. Wenn Name_001
    bereits vorhanden ist, wird dieser eben durch <Name_002> ersetzt usw. Und ich möchte diese Funktion nur einmal
    schreiben für alle Klassen.

    objArr ist der Stapel (Klassisches C-Array) einer beliebigen Klasse, welche die Funktion ToString() besitzt. nObj entspricht der Anzahl der Stapelinhalte.

    Meine Frage ist jetzt, wie ich diese Funktion GetNextName schreiben kann.
    Das Konzept sieht wie folgt aus:

    #include <cstring>
    #include "..\\C1\\CM1_Definition.hpp"
    #include "..\\C2\\CM2_Definition.hpp"
    /*include der Definition aller Klassen*/
    
    #ifndef GETNEXTNAME_HPP
    #define GETNEXTNAME_HPP
    std::string GetNextName(const std::string fName, void* objArr, int nObj) {
    	std::string DummyName = fName;
    	bool NamePresent = false;
    	
    	do {
    		for (int i = 0; i < nObj; i++) {
    			if (objArr.ToString() == DummyName) { /*Error here, because type is not known*/
    				IncrementName(DummyName);
    			}
    		}
    	} while(NamePresent);
    }
    
    std::string IncrementName(std::string fName); /*Funktion passt den bereits vorhandenen Namen an indem es _001 anhängt oder ein vorhandenes _001 in ein _002 umwandelt*/
    #endif
    

    Ich hoffe, ich habe das Problem klar beschrieben.
    Vielen Dank im Voraus.



  • @CJens sagte in Funktion für die Nutzung der Methode ToString() in verschiedenen Klassen.:

    objArr ist der Stapel (Klassisches C-Array) einer beliebigen Klasse, welche die Funktion ToString() besitzt

    Ein klassisches C-Array kann keine Funktionen besitzen. Zeigst du mal dessen Definition?

    Da du den Tag templatefunktio(n) benutzt, nehme ich an, daß du gerne hierfür ein Template erstellen möchtest, oder?
    Die Alternative wäre selbstverständlich eine gemeinsame Basisklasse für die Klassen C1, C2, ... zu benutzen.



  • Hi.

    Vielleicht habe ich mich da unklar ausgedrückt. Das C-Array soll ja die Klassen an sich beinhalten, welche die Funktion ToString() als Methode besitzen. Der Code könnte dann so aussehen:

    int main() {
    	C1* pC1 = (C1*)malloc(5 * sizeof(C1));
    	C2* pC2 = (C2*)malloc(5 * sizeof(C2));
    	for (int i = 0; i < 5; i++) {
    		pC1[i].DefineName("Default Mesh", pC1, 5);
    		pC2[i].DefineName("Default Family", pC2, 5);
    	}
    
    	for (int i = 0; i < 5; i++) {
    		std::cout << pC1[i].ToString().c_str() << std::endl;
    		std::cout << pC2[i].ToString().c_str() << std::endl << std::endl;
    	}
    
    		
    	/*Erwartete Ausgabe:
    	Default Mesh
    	Default Family
    
    	Default Mesh_001
    	Default Family_001
    
    	Default Mesh_002
    	Default Family_002
    
    	Default Mesh_003
    	Default Family_003
    
    	Default Mesh_004
    	Default Family_004
    	*/
    
    	return 0;
    }
    

    Ich weiß nicht, ob man das über ein Template macht. Ich wage mich zu erinnern, dass ich so etwas vor Jahren schon mal ohne Templates gemacht habe.

    Ich möchte an dieser Stelle deutlich machen, dass ich bewusst auf <vector> verzichte, da das hier eine DLL werden soll, auf welche ich über Interop mit C# zugreifen möchte. Das Marshalen wäre mir dann zu kompliziert... aber das ist ja ein anderes Thema.



  • Irgendwie muß die Funktion aber den Datentyp kennen, denn auf void-Objekten kannst du keine Funktionen ausführen.

    Also entweder

    std::string GetNextName<T>(const std::string fName, T* objArr, int nObj) 
    {
        // ...
        for (int i = 0; i < nObj; i++)
            if (objArr[i].ToString() == DummyName)
    }
    

    oder eben per (abstrakter) Basisklasse (und diese dann als Parameter angeben).

    Ich finde es aber kein gutes Design, daß in den Klassenfunktionen von C1, C2, .. auf das äußere Array zugegriffen wird.



  • Ok, danke - ich werde es dann über ein Template versuchen.

    Ich finde dieses Design auch nicht gut, aber die Klasse kann ja nicht wissen, in welchem Stapel sie sich befindet. Es gibt nämlich mehrere Stapel, da diese wiederum ein Teil einer anderen Klasse sind. vielleicht kann man es damit noch eingrenzen - ändert aber nichts an diesem spezifischen Problem.

    Vielen Dank.