(Klassen)templates mit Teils unbekannten, teils bekannten Datentypen?



  • Hi
    Ich hab ne frage, kann ich ein Klassentemplate erstellen in dem gewisse Member vom unbekannten Datentyp T sind, gleichzeitig aber Member mit bereits bekannten Datentypen habe?
    Ich kriegs nicht ganz so hin^^
    Code aus der .h bzw .cpp:

    CPerson.h

    template <class T>
    class CPerson
    {
    public:
    	CPerson();
    	~CPerson();
    
    	void setName(string Name);
    	string getName() { return Name; }
    
    	void setAlter(T age);
    	T getAlter() { return Alter; }
    
    	void setGroesse(T height);
    	T getGroesse() { return height; }
    
    	void setGewicht(T weight);
    	T getGewicht() { return Gewicht; }
    
    private:
    	std::string Name;
    	T Alter;
    	T Groesse;
    	T Gewicht;
    };
    

    CPerson.cpp:

    CPerson::CPerson()
    {
    	Name = '\0';
    
    }
    
    CPerson::~CPerson()
    {
    }
    
    template<class T>
    void CPerson<string>::setName(string Name)
    {
    	this->Name = Name;
    }
    
    template<class T>
    void CPerson<T>::setAlter(T age)
    {
    	Alter = age;
    }
    
    template<class T>
    void CPerson<T>::setGroesse(T height)
    {
    	Groesse = height;
    }
    
    template<class T>
    void CPerson<T>::setGewicht(T weight)
    {
    	Gewicht = weight;
    }
    

    Nun würde ich gern im Standartkonstruktor mein Name-Member mit 0 befüllen, setmethode ist dafür geschrieben, lösche ich aber die Zeile

    template<class T>
    

    vor der Methode setName raus, gibts da auch wieder fehler, obwohl wenn das Member Name eh als string bekannt ist, brauch ich diese Zeile doch gar nicht oder?
    Verwirrt mich etwas, ist sowas denn gar nicht möglich in nem Template?
    Also müsst ich da Name auch als Datentyp T definieren in der gesamten Klasse?



  • Templates mit .cpp-Files wird eh nicht funktionieren. Du brauchst die vollständige Template-Definition zur Kompilierzeit. Du musst alles in den Header schreiben, so wie es in zahllosen Beispielen vorgemacht wird.

    Nun würde ich gern im Standartkonstruktor mein Name-Member mit 0 befüllen ...

    Warum? Genügt es nicht, den Default-Konstruktor von std::string zu verwenden? Der liefert dir einen leeren String. Verabschiede dich von dieser C-Kacke mit den null-terminierten Strings. In C++ braucht dich das nicht zu interessieren.



  • 1. name wird im Konstruktor schon automatisch default-initialisiert, d.h. mit einem Leerstring initialisiert
    2.

    Name = '\0';
    

    würde einen String der Länge 1 (mit dem Null-Charakter) initialisieren (willst du das wirklich?).

    3. Templates müssen komplett im Header als Source vorliegen! Du kannst aber

    #include "person.inl"
    

    (oder wie auch immer du diese Datei dann nennst) am Ende des Headers einbinden.

    PS: Entferne das C aus dem Namen der Klasse...



  • becht schrieb:

    CPerson.h

    template <class T>
    class CPerson
    {
    // ...
    private:
    	std::string Name;
    	T Alter;
    	T Groesse;
    	T Gewicht;
    };
    

    Welchen Sinn soll da ein anderer Typ als int haben?



  • Swordfish schrieb:

    becht schrieb:

    CPerson.h

    template <class T>
    class CPerson
    {
    // ...
    private:
    	std::string Name;
    	T Alter;
    	T Groesse;
    	T Gewicht;
    };
    

    Welchen Sinn soll da ein anderer Typ als int haben?

    Das ganze is eigentlich nur ein Beispiel für mich zum üben um den zusammenhang der verschiedenen Datentypen im Template kennenzulernen bzw wollt ich eben probieren obs hinhaut im Template eben trotzdem nen Namen vom Typ string zu verwenden.
    Der Gedanke war mal das Alter als int, Groesse als float und Gewicht als double (oder float, egal, hauptsache ne Gleitkommazahl) zu verwenden, generell wollte ich halt mal das ganze praktisch anwenden aber ich tu mir da etwas schwer, ich tu mir schwer was leicht erklärtes im Internet zu diesem Thema zu finden.^^



  • becht schrieb:

    template<class T>
    void CPerson< /* hier */ string>::setName(string Name)
    {
    	this->Name = Name;
    }
    

    Hier spezialisierst Du die Funktion CPerson::setName() für T = std::string ... T wird wohl nie ein String sein ...

    becht schrieb:

    [...] generell wollte ich halt mal das ganze praktisch anwenden aber ich tu mir da etwas schwer, ich tu mir schwer was leicht erklärtes im Internet zu diesem Thema zu finden.^^

    #include <string>
    
    template<typename T, typename U, typename V>
    struct Foo{
    	T foo;
    	U bar;
    	V baz;
    	std::string name;
    
    	T get_foo() const { return foo; }
    	U get_bar() const { return bar; }
    	V get_baz() const { return baz; }
    	std::string get_name() const { return name; }
    
    	void set_foo(T t) { return foo = t; }
    	void set_bar(U u) { return bar = u; }
    	void set_baz(V v) { return baz = v; }
    	void set_name(std::string const & n) { name = n; }
    };
    
    int main()
    {
    	Foo<int, float, double> f;
    }
    

    keine Hexerei.



  • Swordfish schrieb:

    becht schrieb:

    template<class T>
    void CPerson< /* hier */ string>::setName(string Name)
    {
    	this->Name = Name;
    }
    

    Hier spezialisierst Du die Funktion CPerson::setName() für T = std::string ... T wird wohl nie ein String sein ...

    becht schrieb:

    [...] generell wollte ich halt mal das ganze praktisch anwenden aber ich tu mir da etwas schwer, ich tu mir schwer was leicht erklärtes im Internet zu diesem Thema zu finden.^^

    #include <string>
    
    template<typename T, typename U, typename V>
    struct Foo{
    	T foo;
    	U bar;
    	V baz;
    	std::string name;
    
    	T get_foo() const { return foo; }
    	U get_bar() const { return bar; }
    	V get_baz() const { return baz; }
    	std::string get_name() const { return name; }
    
    	void set_foo(T t) { return foo = t; }
    	void set_bar(U u) { return bar = u; }
    	void set_baz(V v) { return baz = v; }
    	void set_name(std::string const & n) { name = n; }
    };
    
    int main()
    {
    	Foo<int, float, double> f;
    }
    

    keine Hexerei.

    Ja aber wie sehen die werte in dem objekt jetzt zb aus?
    Du gibst bei der objekterstellung ja keine konkreten werte an, bzw wie befülle ich da den standartkonstruktor?
    Ich weiß ja banal gesagt nicht ob jetzt der Datentyp nen char, int etc. ist, da kann ich im Standartkonstruktor ja jetzt nicht die unbekannten variablen als 0 definieren.

    Ich mach ne Ausbildung zum programmierer und uns wurde halt gesagt im Standartkonstruktor muss man Member immer auf gültige Werte initialisieren (Pointer auf NULL setzen, int auf 0 bzw was fallweise halt als zumindest gültig angesehen wird..)
    In deinem Beispiel ist aber noch nichtmal ein Konstruktor vorhanden, welche Werte würde der jetzt da in die diversen Member reinspeichern, irgendwelche oder?
    Bzw wäre ich in dem Fall ja gezwungen die setmethoden für alle member auszuführen bevor ich mit dem Objekt weiterarbeite weil ja unbekannt ist was eigentlich für Werte gespeichert wurden?

    Aber danke schonmal für die bisherige Hilfe!
    Im großen und ganzen tu ich mir sehr leicht C++ zu verstehen aber bei den Templates da hauts mich total auf 🙄



  • template<typename T, typename U, typename V>
    struct Foo{
        T foo = T();
        U bar = U();
        V baz = V();
    ...
    


  • becht schrieb:

    Ja aber wie sehen die werte in dem objekt jetzt zb aus?

    Swordfish schrieb:

    Foo<int, float, double> f;
    

    Die Member von Foo werden hier default-initialized.
    foo , bar , baz haben indeterminate value,
    name wird durch den Standardkonstruktor von std::string auf den leeren String "" gesetzt.

    becht schrieb:

    Du gibst bei der objekterstellung ja keine konkreten werte an, bzw wie befülle ich da den standartkonstruktor?

    Mein Foo hat auch nur den Compilergenerierten default-Konstruktor. Aber es geht list-initialization:

    Foo<int, float, double> f{42, 4.2f, 0.42, "Foobar"};
    

Log in to reply