Klassen und wie ich in Friendfunktionen auf Elemente zugreife -- (viele)Fragen :)



  • Hallo zusammen
    Ich bin neu hier im Forum und verzweifelt auf der Suche nach Hilfe. Ich stecke im zweiten Semester E-Technik und muss für Info eine Klasse safe_int schreiben, durch die Zahlbereichsüberschreitungen während des Rechnens erkannt werden.
    Der Prof hat viele Codefragmente in die Aufgabe eingebaut, aber beim Zusammenfrickeln haben sich da für mich viele Probleme ergeben die Syntax korrekt hinzukriegen. Es sind einfach zuviele Sachen neu und er erklärt viel zu wenig.
    Versteh ich wenn sich diese "Wall of Code" nicht jeder antuen will, aber vielleicht hat ja jemand von euch heute nen sozialen Tag 😉

    So sieht meine Klasse bisher aus:

    #include <limits>
    #include <iostream>
    #include <stdio.h>
    #include <sstream>
    #include <string>
    using namespace std;
    
    class safe_int{
       private:
          int val;
          static const string limit_string;
          static string lim_to_string();
          static int divi(int,int);
          static int mod(int,int);
    
       public: 
          static const int lim;        
          class overflow {};
          safe_int(int) throw(overflow);
          safe_int() throw();
          friend safe_int operator+(safe_int,safe_int) throw(safe_int::overflow);
          friend safe_int operator-(safe_int,safe_int) throw(safe_int::overflow);
          friend safe_int operator*(safe_int,safe_int) throw(safe_int::overflow);
          friend safe_int operator/(safe_int,safe_int) throw(safe_int::overflow);
          friend safe_int operator%(safe_int,safe_int) throw(safe_int::overflow);
          friend ostream& operator<<(ostream&,safe_int) throw(safe_int::overflow);
          friend istream& operator>>(istream&,safe_int) throw(safe_int::overflow);         
    };
    

    Direkt dahinter definiere(??) ich const int lim (max positive darstellbare Zahl...also meist 2147483647) folgendermaßen:

    const int safe_int::lim=numeric_limits<int>::max();
    

    und weil ich eingegebne Zahlen auch als String mit lim vergleichen muss, wird
    lim auch in einen String umgewandelt:

    const string safe_int::limit_string=lim_to_string();
    
    string safe_int::lim_to_string(){
    ostringstream ostr;
    ostr<<lim;
    return ostr.str();
    }
    

    //Und dann beginnen die Fehlermeldungen im überladenem >> Operator:

    istream &operator>>(istream &is,safe_int &a) throw(safe_int::overflow){
    is>>ws;
    int sign=is.peek();
    if(sign=='+'||sign=='-') is.get();
    string zahl;
    while(isdigit(is.peek())){
       zahl+=is.get();  
                              }//of while
    if(zahl.size()==0){
       if(sign=='+'||sign=='-'){
       is.putback(sign);
                                }//of if Vorzeichen
    is.setstate(ios_base::failbit);                 
                      }//of if keine Zahl eingelesen
    if(zahl.size()> safe_int::limit_string.size() ||zahl.size()==safe_int::limit_string.size()&& zahl>safe_int::limit_string){
          throw safe_int::overflow();  
                                                                                                                            } 
    istringstream istr(zahl);
    istr>>a.val;
    if(sign=='-') a.val=-a.val;                 
    
    }//of operater >> EINGABE
    

    Den Code für diesen Operator habe ich quasi 1:1 aus seiner Aufgabenstellung entnommen. Aber bei z.B. "safe_int::limit_string.size()" meckert der Compiler
    `const std::string safe_int::limit_string' is private within this Context
    Verstehe ich nicht, da >>Operator doch ein friend von safe_int ist

    Das nächste Problem was häufig angemeckert wird findet sich in den +/-/%/ Opteratoren: declaration of `safe_int operator+(safe_int, safe_int)' throws different exceptions than previous declaration `safe_int operator+(safe_int, safe_int) throw (safe_int::overflow)' Verstehe ich auch nicht, da die einzige exception die ich benutze doch safe_int::overflow ist?? Allerdings muss ich gestehen, dass ich das mit dem Overflow noch nicht kapiert habe, wie eine leere Klasse jetzt vernünftig reagieren soll^^*
    Hier mein Code für den +Operator der diesen Fehler produziert

    safe_int operator+(safe_int a,safe_int b){
        safe_int erg;
        if((b.val>0 && a.val>lim-b.val) || (b.val<0 && -a.val>lim+b.val)){
           throw(safe_int::overflow);       
                                                                          }
        erg.val=a.val+b.val;                                                                  
    return erg;    
    }
    

    **Das zweite was er hieran meckert ist, das er lim nicht kennt. Wie muss ich in einer Friendfunktion eine Konstante einer Klasse aufrufen?
    **

    Hmmm...das wars erstmal von der Front. Wenn ihr mehr Fehlermeldungen hören wollt meldet euch. Die gehen mir so schnell nicht aus 😃
    Hoffe jemand kann mir armen Wicht helfen.
    Schönen Tag euch

    Epi



  • Hier das ganze "Meisterwerk" (sieht so cool aus mit der cpp Formatierung:

    #include <limits>
    #include <iostream>
    #include <stdio.h>
    #include <sstream>
    #include <string>
    using namespace std;
    
    class safe_int{
       private:
          int val;
          static const string limit_string;
          static string lim_to_string();
          static int divi(int,int);
          static int mod(int,int);
    
       public: 
          static const int lim;        
          class overflow {};
          safe_int(int) throw(overflow);
          safe_int() throw();
          friend safe_int operator+(safe_int,safe_int) throw(safe_int::overflow);
          friend safe_int operator-(safe_int,safe_int) throw(safe_int::overflow);
          friend safe_int operator*(safe_int,safe_int) throw(safe_int::overflow);
          friend safe_int operator/(safe_int,safe_int) throw(safe_int::overflow);
          friend safe_int operator%(safe_int,safe_int) throw(safe_int::overflow);
          friend ostream& operator<<(ostream&,safe_int) throw(safe_int::overflow);
          friend istream& operator>>(istream&,safe_int) throw(safe_int::overflow);         
    };
    const int safe_int::lim=numeric_limits<int>::max();
    const string safe_int::limit_string=lim_to_string();
    
    string safe_int::lim_to_string(){
    ostringstream ostr;
    ostr<<lim;
    return ostr.str();
    }
    
    ostream& operator<<(ostream&,safe_int a) throw(safe_int::overflow){
        cout<<a.val;         
    }
    
    istream &operator>>(istream &is,safe_int &a) throw(safe_int::overflow){
    is>>ws;
    int sign=is.peek();
    if(sign=='+'||sign=='-') is.get();
    string zahl;
    while(isdigit(is.peek())){
       zahl+=is.get();  
                              }//of while
    if(zahl.size()==0){
       if(sign=='+'||sign=='-'){
       is.putback(sign);
                                }//of if Vorzeichen
    is.setstate(ios_base::failbit);                 
                      }//of if keine Zahl eingelesen
    if(zahl.size()> safe_int::limit_string.size() ||zahl.size()==safe_int::limit_string.size()&& zahl>safe_int::limit_string){
          throw safe_int::overflow();  
                                                                                                                            } 
    istringstream istr(zahl);
    istr>>a.val;
    if(sign=='-') a.val=-a.val;                 
    
    }//of operater >> EINGABE
    
    void menue(safe_int a,safe_int b,char op);
    char operaEinlesen();
    
    //**************************************************MAIN***************************************************
    
    int main(){
       	char opera,bee='n';
       	safe_int zahl1,zahl2;
    	do{
          cout<<"Bitte geben sie die erste Zahl ein:"<<endl;
          cin>>zahl1;       
          opera=operaEinlesen();
          cout<<"Bitte geben sie die zweite Zahl ein:"<<endl; 
          cin>>zahl2;
          menue(zahl1,zahl2,opera);
          cout<<"Moechten Sie das Programm beenden:Druecken sie eine beliebige Taste\n Druecken Sie ""n"" um weitere safe_int Berechnungen durchzufuehren.";
    	  cin>>bee;
    	 }while(bee=='n');      
    }//of main
    
    //************************************************************************************************************
    
    safe_int operator+(safe_int a,safe_int b){
        safe_int erg;
        if((b.val>0 && a.val>lim-b.val) || (b.val<0 && -a.val>lim+b.val)){
           throw(safe_int::overflow);       
                                                                          }
        erg.val=a.val+b.val;                                                                  
    return erg;    
    }
    
    safe_int operator-(safe_int a,safe_int b){
        safe_int erg;    
        if((b.val>0 && -a.val>lim-b.val) || (b.val<0 && a.val>lim+b.val)){
           throw(safe_int::overflow);       
                                                                         }
        erg.val=a.val-b.val;                                                                 
    return erg;    
    }
    
    safe_int operator*(safe_int a,safe_int b){
        int ba,bb;
        safe_int erg;
        if(a.val<0){
           ba=a.val*-1; 
                   }
           else ba=a.val;     
        if(b.val<0){
           bb=b.val*-1;     
                }
           else bb=b.val;     
        //cout <<bb;
        //cout <<"\n";
        //cout <<lim;                
        if(b.val !=0 && ba > lim/bb){
           throw(safe_int::overflow);       
                                    }
        erg.val=a.val*b.val;                    
    return erg;        
    }
    
    safe_int operator/(safe_int a,safe_int b){
       safe_int erg;
       int c,aa,bb;
       aa=a.val;
       bb=b.val;
       c=safe_int::divi(aa,bb);
       erg.val=c;
    return erg;
    }
    
    safe_int operator%(safe_int a,safe_int b){
       safe_int erg;
       int c,aa,bb;
       aa=a.val;
       bb=b.val;   
       c=safe_int::mod(aa,bb);
       erg.val=c;
    return erg;    
    }
    
    int safe_int::divi(int a,int b){
    int q,r;
    
       if(b==0){
          throw (safe_int::overflow);       
                 }
       q=a/b;
       r=a-q*b;
       if(a<0)
          {
          if(r>0)
             if(b>0)
           	    q=q+1;
                else
              	    q=q-1;
          }
       else
          if(r<0) 
             q=q+1;
    
    return q;    
    }
    
    int safe_int::mod(int a,int b){
    int q,r;
     if(b==0){
        throw (safe_int::overflow);        
             }
     q=a/b;
     r=a-q*b;
       if(a<0){
    
       if(r>0)
          if(b>0)
    	     r=r-b;
             else{
    	         r=r+b;
                 }
             }
       else
          if(r<0){
                 r=r-b;
                 }
    
    return r;    
    }
    
    void menue(safe_int a,safe_int b,char op){
         safe_int erg;
         switch(op){
               case '+':{
                        try{
                           erg=a+b;
                           cout <<"\nDas Ergebnis der Addition lautet:"<<erg;
                           }
                        catch(){
                              cout<<"overflow bei "<<endl;
                              //cout <<"\nDas Ergebnis der Addition lautet:"<<erg;
                             }  
                        break;
                        }//case +
               case '-':{
                        try{
                           erg=a-b;
                           cout <<"\nDas Ergebnis der Subtraktion lautet:"<<erg;
                           }
                        catch(){
                              cout<<"overflow bei "<<endl;
                              //cout <<"\nDas Ergebnis der Subtraktion lautet:"<<erg;
                             }                  
                        break;
                        }//case +
               case '*':{
                        try{
                           erg=a*b;
                           cout <<"\nDas Ergebnis der Multiplikation lautet:"<<erg;
                           }
                        catch(){
                              cout<<"overflow bei "<<endl;
                              //cout <<"\nDas Ergebnis der Multiplikation lautet:"<<erg;
                             }                  
                        break;
                        }//case +
               case '/':{
                        try{
                           erg=a/b;
                           cout <<"\nDas Ergebnis der Division lautet:"<<erg;
                           }
                        catch(){
                              cout<<"overflow bei "<<endl;
                              //cout <<"\nDas Ergebnis der Division lautet:"<<erg;
                             }                  
                        break;
                        }//case +
               case '%':{
                        try{
                           erg=a%b;
                           cout <<"\nDas Ergebnis der Modulooperation lautet:"<<erg;
                           }
                        catch(){
                              cout<<"overflow bei "<<endl;
                              //cout <<"\nDas Ergebnis der Modulooperation lautet:"<<erg;
                             }                  
                        break;
                        }//case +  
               default: cout <<"Diesen Text wird nie jemand lesen.";                                                                                        
    
                    }//of switch
    }//of menue
    
    char operaEinlesen(){
           int ianz,fehler=0;
           char zeichen;
           cout <<"Bitte geben sie einen gueltigen Operator an (+,-,*,/,%):\n"; 
           do{ 
             ianz=scanf("%c",&zeichen);
             fflush(stdin);
             if (zeichen=='+' || zeichen=='/' || zeichen=='*' || zeichen=='-' || zeichen=='%'){
                fehler=0;
                                                                                                           }
                else{
                     cout <<"Eingabefehler. Bitte geben sie einen gueltigen Operator an (+,-,*,/,%):\n";
                     fehler=1;
                     }
    
            }while (ianz!=1 || fehler==1); 
    return zeichen;                
    }//of operaEinlesen
    


  • Epimetheus schrieb:

    ...

    ...
    class safe_int{
    ...
          istream &operator>>(istream,safe_int) throw(safe_int::overflow);
    ...
    

    <=>

    Epimetheus schrieb:

    ...

    istream &operator>>(istream &is,safe_int &a) throw(safe_int::overflow){
    

    ...

    Ist nicht dieselbe Funktionssignatur.
    Deswegen "befriendet" die friend clause auch die u.g. Funktion nicht.
    => Kein Zugriff auf private Member.

    Übrigens: Ich würde mit "friend" seeehr sparsam sein - und konkret hier weglassen.
    Besser:
    A) public member function definieren (scan(), print()) und die vom operator>>()/operator<<() aufrufen.
    😎 safe_int::getLimitSize(); definieren.

    Gruß,

    Simon2.


  • Mod

    friend istream& operator>>(istream&,safe_int[b]&[/b]) throw(safe_int::overflow);
    

    von Exceptionspezifikationen ist abzuraten.



  • camper schrieb:

    von Exceptionspezifikationen ist abzuraten.

    agreed.
    http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=109&rl=1

    spambusterüberlistung.spambusterüberlistung.spambusterüberlistung.spambusterüberlistung.spambusterüberlistung.spambusterüberlistung.
    spambusterüberlistung.spambusterüberlistung.spambusterüberlistung.spambusterüberlistung.spambusterüberlistung.spambusterüberlistung.
    spambusterüberlistung.spambusterüberlistung.spambusterüberlistung.spambusterüberlistung.spambusterüberlistung.spambusterüberlistung.
    spambusterüberlistung.spambusterüberlistung.spambusterüberlistung.spambusterüberlistung.spambusterüberlistung.spambusterüberlistung.
    spambusterüberlistung.spambusterüberlistung.spambusterüberlistung.spambusterüberlistung.spambusterüberlistung.spambusterüberlistung.
    spambusterüberlistung.spambusterüberlistung.spambusterüberlistung.spambusterüberlistung.spambusterüberlistung.spambusterüberlistung.
    spambusterüberlistung.spambusterüberlistung.spambusterüberlistung.spambusterüberlistung.spambusterüberlistung.spambusterüberlistung.



  • Die Exceptionspezifikationen hat er auf dem Aufgabenblatt aufgeführt und die hab ich wie gesagt auch nicht verstanden. 🙂 Also weg damit.

    A) public member function definieren (scan(), print()) und die vom operator>>()/operator<<() aufrufen.

    Was das bedeutet weiß ich leider nicht. Haben Klassen jetzt seit 6 Vorlesungen und das letzte was wir gemacht haben war Vererbung. Bin da also nicht so wirklich fit. Aber danke für die Hilfe soweit 👍



  • Hi,

    ist nicht schwer:

    class safe_int{
    ... 
       public:
          istream& scan(istream&); // Hier machst Du die Implementation der EinleseRoutine
          ostream& print(ostream&) const; // Hier machst Du die Implementation der AusgabeRoutine
    };
    
    ostream& operator<<(ostream& ost, safe_int const& i) { return i.print(ost); }
    istream& operator>>(istream& ist ,safe_int& i) { return i.scan(ist); }
    

    Ist ein Idiom, das viele Vorteile hat, weswegen ich es immer anwende....

    Gruß,

    Simon2.



  • Super. Danke für den Tipp.
    Eine Sache hab ich noch selber rausgefunden: Das er lim nicht kennt liegt schlicht und ergreifend daran, dass ich es einfach lim nenne in einer Friendfunktion.
    Es muss natürlich safe_int::lim heißen. 😮



  • soo...in der neuen Aufgabe sollen wir die Friendfunktionen in Komponentenfunktionen umwandeln. Und dabei hat sich ein neues Problem ergeben:

    Ich hab den Tip bekommen das man, um a=b+c+d //a,b,c,d sind safe_int
    gescheit rechnen zu können, beim operator+ eine Referenz zurückgegeben werden muss(??).
    Dadurch verändert sich meine Klasse folgendermaßen:

    class safe_int{
       private:
          int val;
          static const string limit_string;
          static string lim_to_string();
          static int divi(int,int);
          static int mod(int,int);
    
       public: 
          static const int lim;        
          class overflow {
          	public:
    		int op1,op2;
    		char func[30];
    		overflow(char *f,int i,int j){
    			op1=i;
    			op2=j;
    			strcpy(func,f); 
    		                             }
    	    };//of class overflow 
    
          safe_int(string zahl);
          safe_int() throw() {val=0;}
          safe_int& operator+(safe_int b);
          safe_int& operator-(safe_int b);
          safe_int& operator*(safe_int b);
          safe_int& operator/(safe_int b);
          safe_int& operator%(safe_int b);
          friend ostream& operator<<(ostream&,safe_int);
          friend istream& operator>>(istream&,safe_int&);         
    };
    

    Mein Komponenten-Operator + sieht jetzt so aus:

    safe_int& safe_int::operator+(safe_int b){
    
        safe_int erg;
        if((b.val>0 && val>lim-b.val) || (b.val<0 && -val>lim+b.val)){
           throw overflow("Addition",val,b.val);       
        erg.val=val+b.val;                                                                  }                                                                  
    return erg;    
    }
    

    Das das so nicht funktionieren kann ist mir bewusst, weil man keine Referenz auf eine lokale Variable binden darf bzw. das Unsinn ist. Allerdings weiß ich nicht wie ich das Ergebnis vernünftig zurückgeben kann.
    Mitlerweile hat sich bei mir wieder ein Zustand größter Verwirrung eingestellt. 😕
    Ich wäre super dankbar wenn mir wer sagen könnte wie das geht. Denn dann bin ich in der Lage alle weiteren Aufgaben zu lösen.

    Epi 🙂



  • Gib eine Kopie zurück.


Anmelden zum Antworten