Klassenprobleme



  • Hallo Leute,

    ich habe zwei Klassen(templates) geschrieben, die sich gegenseitig in ihren Operatoren benötigen. Die SD_Number_long Klasse benötigt die SD_Number Klasse als Argument für den + & - Operator. Die SD_Number Klasse gibt beim Operator + ein SD_Number_long zurück. D.h. meine beiden Klassen benötigen sich gegenseitig. Gegenseitig includen geht nicht (Endlosschleife) u. forward ref. bringts auch nicht, weil ich in den Operatoren wirklich mit den entsprechenden Instanzen der Klassen arbeite!
    Tschia, was macht man da??

    Hier mal der Problemcode:

    sd_digit.h

    #ifndef SD_DIGIT
    #define SD_DIGIT
    
    #include "systemc.h"
    #include "sd_digit_long.h"
    
    typedef enum sd_digit {MINUS_ONE=-1, ZERO=0, ONE=1} ;
    
    template <class T, int Groesse>
    
    class SD_Number
      {
        public:
          T a[Groesse];   // Groesse ist bekannt
          SD_Number() ;
          SD_Number_long& operator+(SD_Number B) ;
          // weitere
    
        private:
          int seineGroesse ;
    } ;
    
    template <class T, int Groesse>
    SD_Number<T, Groesse>::SD_Number()
    {
    	seineGroesse = Groesse ;
    	for (int lv = 0; lv < Groesse; lv++)
    		a[lv] = ZERO ;
    }
    
    template <class T, int Groesse>
    SD_Number_long<T, Groesse>& SD_Number<T, Groesse>::operator+ (SD_Number B)
    {
    	sd_digit               S_Vektor[Groesse], C_Vektor[Groesse+1] ;
    	int                    zwisch_erg[Groesse], i ;
    
    	for (i = 0; i < Groesse; i++) {   // Schritt 1 der SD-Additon
    		zwisch_erg[i] = this->a[i] + B.a[i] ;
    		switch (zwisch_erg[i]) {
    			case -1:	// Addition von 0+(-1)
    				S_Vektor[i]   = MINUS_ONE ;
    				C_Vektor[i+1] = ZERO ;
    				break ;
    			case 0: // Addition von 0+0 bzw. 1+(-1) pro Bit
    				S_Vektor[i]   = ZERO ;
    				C_Vektor[i+1] = ZERO ;
    				break ;
    			case 1:	// Addition von 0+1 bzw. 1+0 pro Bit
    				S_Vektor[i]   = MINUS_ONE ;
    				C_Vektor[i+1] = ONE ;
    				break ;
    			case 2: // Addition von 1+1 pro Bit
    				S_Vektor[i]   = ZERO ;
    				C_Vektor[i+1] = ONE ;
    				break ;
    		} ;
    	} ;
    
    	C_Vektor[0] = ZERO ;   // Null nachziehen in LSB des C-Vektors
    
    	for (i = 0; i < Groesse; i++) {   // Schritt 2 der SD-Additon
    		zwisch_erg[i] = S_Vektor[i] + C_Vektor[i] ;
    		switch (zwisch_erg[i]) {
    			case -1: // Addition von MINUS_ONE+ZERO pro SD-Ziffer
    				this->a[i] = MINUS_ONE ;
    				break ;
    			case 0:	// Addition von ZERO+ZERO bzw. MINUS_ONE+ONE pro SD-Ziffer
    				this->a[i] = ZERO ;
    				break ;
    			case 1: // Addition von ZERO+ONE pro Bit
    				this->a[i]   = ONE ;
    				break ;
    		} ;
    	} ;
    
    	this->a[Groesse] = C_Vektor[Groesse];		// führendes ErgebnisDigit = erstes C_VektorDigit
    
    	return (*this) ;
    }
    

    sd_digit_long.h

    #ifndef SD_DIGIT_LONG
    #define SD_DIGIT_LONG
    
    #include "systemc.h"
    #include "sd_digit.h"
    
    template <class T, int Groesse>
      class SD_Number_long  {
    
    public:
          T a[Groesse];   // Groesse ist bekannt
    
          SD_Number_long() ;
          SD_Number_long& operator+(SD_Number<T,Groesse-1> B);
          SD_Number_long& operator-(SD_Number<T,Groesse-1> B);
          // weitere
    
       private:
          int seineGroesse ;
    } ;
    
    template <class T, int Groesse>
    SD_Number_long<T, Groesse>::SD_Number_long()
    {
    	seineGroesse = Groesse ;
    	for (int lv = 0; lv < Groesse; lv++)
    		a[lv] = ZERO ;
    }
    
    template <class T, int Groesse>
    SD_Number_long<T,Groesse>& SD_Number_long<T, Groesse>::operator+(SD_Number<T,Groesse-1> B) {
    
    	const int size = Groesse-1;
    	sd_digit							S_Vektor[Groesse], C_Vektor[Groesse+1] ;
    	int									zwisch_erg[Groesse], i ;
    
    	for (i = 0; i < size; i++) {   // Schritt 1 der SD-Additon
    		zwisch_erg[i] = this->a[i] + B.a[i] ;
    		switch (zwisch_erg[i]) {
    			case -1:	// Addition von 0+(-1)
    				S_Vektor[i]   = MINUS_ONE ;
    				C_Vektor[i+1] = ZERO ;
    				break ;
    			case 0: // Addition von 0+0 bzw. 1+(-1) pro Bit
    				S_Vektor[i]   = ZERO ;
    				C_Vektor[i+1] = ZERO ;
    				break ;
    			case 1:	// Addition von 0+1 bzw. 1+0 pro Bit
    				S_Vektor[i]   = MINUS_ONE ;
    				C_Vektor[i+1] = ONE ;
    				break ;
    			case 2: // Addition von 1+1 pro Bit
    				S_Vektor[i]   = ZERO ;
    				C_Vektor[i+1] = ONE ;
    				break ;
    
    		} ;
    
    	} ;
    
    	switch (a[Groesse-1]) {
    		case -1:
    			S_Vektor[Groesse-1]	= MINUS_ONE ;
    			C_Vektor[Groesse]	= ZERO ;
    			break;
    		case 0:
    			S_Vektor[Groesse-1]	= ZERO ;
    			C_Vektor[Groesse]	= ZERO ;
    			break;
    		case 1:
    			S_Vektor[Groesse-1]	= MINUS_ONE ;
    			C_Vektor[Groesse]	= ONE ;
    			break;
    
    	};
    
    	C_Vektor[0] = ZERO ;   // Null nachziehen in LSB des C-Vektors
    
    	for (i = 0; i < Groesse; i++) {   // Schritt 2 der SD-Addition
    		zwisch_erg[i] = S_Vektor[i] + C_Vektor[i] ;
    		switch (zwisch_erg[i]) {
    			case -1: // Addition von MINUS_ONE+ZERO pro SD-Ziffer
    				this->a[i] = MINUS_ONE ;
    				break ;
    			case 0:	// Addition von ZERO+ZERO bzw. MINUS_ONE+ONE pro SD-Ziffer
    				this->a[i] = ZERO ;
    				break ;
    			case 1: // Addition von ZERO+ONE pro Bit
    				this->a[i]   = ONE ;
    				break ;
    		} ;
    	} ;
    
    	if (C_Vektor[Groesse] == ONE) {
    		bool exit = false;
    		i = Groesse-1;
    		while (exit == false) {
    			if (this->a[i] == MINUS_ONE) {
    				for (int lauf = Groesse-1; lauf >= i; lauf--) {
    					this->a[lauf] = ONE;
    				};
    				exit = true;
    			}
    			else i--;
    		};
    	};
    
    	return (*this) ;
    }
    
    template <class T, int Groesse>
    SD_Number_long<T, Groesse>& SD_Number_long<T, Groesse>::operator- (SD_Number<T,Groesse-1> B)
    {
    	SD_Number<T, Groesse>  temp ;
    
    	for (int i = 0; i < Groesse-1; i++) {   // Invertieren des zweiten Operanden
    		switch (B.a[i]) {
    			case MINUS_ONE: // aus -1 wird +1
    				temp.a[i]   = ONE ;
    				break ;
    			case ZERO:	// 0 bleibt 0
    				temp.a[i]   = ZERO ;
    				break ;
    			case ONE: // aus +1 wird -1
    				temp.a[i]   = MINUS_ONE ;
    				break ;
    		} ;
    	} ;
    
    	(*this) = (*this) + temp ;
    
    	return (*this) ;
    }
    


  • Eigentlich brauchen doch nur die Operatoren die beiden Klassen, die Klassen sich aber nicht gegenseitig, wenn ich Deinen Text richtig interpretiert habe.
    Demnach könntest Du die Operatoren einfach auslagern in einen eigenen Header, oder die Implementierung in die cpp verschieben und im Header nur die Deklaration stehen lassen... dann klappt's auch mit der Forward-Deklaration.

    MfG Jester



  • Na klar, könnte hinhauen. 😃 Ich probiers mal so und poste obs geklappt hat.
    Danke dir!! MfG mdsnake



  • Danke Jester, es hat funktioniert!

    Nochmal ne kleine andere Frage. Wie deklariert man eine Attribut für ein Objekt und weißt ihm gleich einen Wert zu?? Also etwas der Art:
    "private: int groesse = 10; " Im Header geht das anscheinend nicht,was auch Sinn macht. Aber im *.cpp klappts trotz static & const Deklarierung irgendwie auch nicht,hmm.... ??Bin ich nur blond??

    MfG mdsnake



  • class Foo {
    private:
    const int bar = 12;
    };

    Für alles andere gibt es doch die Konstruktoren.



  • Genau so hatte ich mir das ja auch gedacht! Wenn ichs genau so mache,bekomme ich aber immer eine Fehlermeldung:
    error C2258: Ungueltige Syntax fuer rein virtuelle Methode; '= 0' erforderlich
    error C2252: 'seineGroesse' : Nur Funktionen koennen rein virtuell deklariert werden

    Häääh.... 😕



  • Zeig mal genau den COde mit dem Fehler, und verwende bitte die c/c++ Code Tags
    dafür, damit es in Farbe ist 🙂



  • SirLant schrieb:

    class Foo {
      private:
        const int bar = 12;
    };
    

    nein.
    static vergessen?

    class Foo {
    private:
       static const int bar = 12;
    };
    

    wenn bar nur eine Compiletimekonstante sein soll.
    Andernfalls, wenn jede Instanz ihre eigene Konstante haben soll

    class Foo {
       const int bar;
    public:
       Foo () : bar(42) {} //so, in elementinitialisierungsliste initialisieren
    


  • Hoppla hab ich doch tatsächlich das static vergessen 🤡



  • Auch mit static kommt die selbe Meldung!
    Also hier mal der Code:
    sd_digit_long.h

    #pragma once
    
    #include "systemc.h"
    #include "wordlength.h"
    
    class SD_Number;
    
    class SD_Number_long  {
    
    	public:
    
    		sd_digit a[WORDLENGTH];   // Groesse ist bekannt
    
    	SD_Number_long() ;
    
    	SD_Number_long(const SD_Number_long &rhs) ;
    
    	SD_Number_long& operator=(const SD_Number_long &rhs);
    
    	SD_Number_long& operator=(int A) ;
    
    	bool operator == (const SD_Number_long& rhs) const ;
    
    	SD_Number_long& operator << (int positions) ;
    
    	SD_Number_long& operator+ (SD_Number_long B) ;
    
    	SD_Number_long& operator- (SD_Number_long B) ;
    
    // Plusoperator für Addition mit "kürzerer" SD_Number (Wordlength-1 Stellen)
    	SD_Number_long& operator+(SD_Number B) ;
    
    	SD_Number_long& operator- (SD_Number B) ;
    
    	private:
    		static const int seineGroesse = 10;
    };
    


  • Vielleicht ist Dein Compiler zu alt und kann das noch nicht. Probier die Zuweisung mal in der Definition in der Implementierung oder suche (im Forum oder bei google) mal nach "enum hack".

    MfG Jester



  • Lag doch tatsächlich an MVC 6.0, der Compiler ist halt doch nicht mehr der neuste. Hab im entsprechenden Forum aber ne gute Lösung gefunden. Danke nochmal!

    MfG mdsnake


Anmelden zum Antworten