Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Klassendesign(achtung lang) -kritik erwünscht!

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 < [ 2 ]
000
22.12.2003, 13:48 Uhr
(un)wissender
Niveauwart


Hallo!

Ich habe mal eine Klasse Bruch erstellt, weil mit die ungenauen doubles nicht passen und um allgemein C++ zu üben.
Jetzt seid ihr gefragt:
Laßt alles raus was euch einfällt, macht mich richtig nieder.
(Performance, Bugs, Designfehler, Verbesserungen, ...)

Der Header

C++:
#ifndef FRACTION_HPP_INCLUDED
#define FRACTION_HPP_INCLUDED

#include <cmath>
#include <exception>
#include <stdexcept>
#include <iostream>
#include <algorithm>

class Fraction {      
    public:
        Fraction(int numerator, int denominator = 1);      
              
        Fraction& operator/=(const Fraction& fraction)
        { return (*this *= fraction.reciprocalValue()); }
                              
        Fraction& operator*=(const Fraction& fraction)
        {  m_numerator *= fraction.m_numerator;
           m_denominator *= fraction.m_denominator;
           return *this; }
        
        Fraction& operator-=(const Fraction& fraction);              
        Fraction& operator+=(const Fraction& fraction);
          
          
        friend inline const Fraction operator*(const Fraction& lhf,  
                                               const Fraction& rhf);
        friend inline const Fraction operator/(const Fraction& lhf,  
                                               const Fraction& rhf);
        friend inline const Fraction operator+(const Fraction& lhf,  
                                               const Fraction& rhf);
        friend inline const Fraction operator-(const Fraction& lhf,  
                                               const Fraction& rhf);  
        
        friend std::ostream& operator<<(std::ostream& out,
                                        const Fraction& fraction);
        friend std::istream& operator>>(std::istream& in, Fraction& fraction);
          
        friend inline bool operator==(const Fraction& lhf, const Fraction& rhf)
        { return lhf.m_numerator * rhf.m_denominator == //Brüche erweitern  
                 rhf.m_numerator * lhf.m_denominator; }
                
        friend inline bool operator!=(const Fraction& lhf, const Fraction& rhf)
        { return !(lhf == rhf); }
        
        friend inline bool operator<(const Fraction& lhf, const Fraction& rhf)
        { return lhf.m_numerator * rhf.m_denominator < //Brüche erweitern  
                 rhf.m_numerator * lhf.m_denominator; }
                                  
        friend inline bool operator>(const Fraction& lhf, const Fraction& rhf)
        { return !(lhf < rhf) && lhf != rhf; }
        
        friend inline bool operator>=(const Fraction& lhf, const Fraction& rhf)
        { return !(lhf < rhf); }
        
        friend inline bool operator<=(const Fraction& lhf, const Fraction& rhf)
        { return !(lhf > rhf); }
        
        //Den ggT (größter gemeinsamer Teiler) berechnen.
        //Nach dem binären Euklidische Algorithmus.
        int greatestCommonDivisor() const;
    
        //Denn Kehrwert berechnen.
        const Fraction reciprocalValue() const
        { return Fraction(*this).reciprocalValue(); }
    
        Fraction& reciprocalValue()
        { std::swap(m_numerator, m_denominator); return *this; }  
            
        //Als double zurückgegebn, Präzesionsverlust möglich.
        double toDouble() const
        { return static_cast<double>(m_numerator) /
                 static_cast<double>(m_denominator); }
      
        //Einen Bruch kürzen.
        Fraction& cut();  
        const Fraction cut() const
        { return Fraction(*this).cut(); }
    
    private:
        int m_numerator, m_denominator; //Zähler,Nenner    
};

#endif



Die Implementierung

C++:
#include "Fraction.hpp"

Fraction::Fraction(int numerator, int denominator)
{
    if(denominator == 0)
        throw std::logic_error("The denominator cannot be null!");
    m_numerator = numerator;
    m_denominator = denominator;
}

Fraction& Fraction::operator-=(const Fraction& fraction)
{    
     //Brüche erweitern
    int numerator = fraction.m_numerator * m_denominator;        
    m_denominator              *= fraction.m_denominator;
    m_numerator                *= fraction.m_denominator;
    
    m_numerator -= numerator;
    
    return *this;
}            

Fraction& Fraction::operator+=(const Fraction& fraction)
{
     //Brüche erweitern
    int numerator = fraction.m_numerator * m_denominator;        
    m_denominator              *= fraction.m_denominator;
    m_numerator                *= fraction.m_denominator;
    
    m_numerator += numerator;
    
    return *this;
}    

                
const Fraction operator*(const Fraction& lhf, const Fraction& rhf)
{
    return Fraction(lhf.m_numerator   * rhf.m_numerator,
                    lhf.m_denominator * rhf.m_denominator);    
}

const Fraction operator/(const Fraction& lhf, const Fraction& rhf)
{
    return lhf * rhf.reciprocalValue();      
}

const Fraction operator+(const Fraction& lhf, const Fraction& rhf)
{
    return Fraction(lhf) += rhf;
}

const Fraction operator-(const Fraction& lhf, const Fraction& rhf)
{
    return Fraction(lhf) -= rhf;
}

std::ostream& operator<<(std::ostream& out, const Fraction& fraction)
{
    return out << fraction.m_numerator << "/" << fraction.m_denominator;    
}

std::istream& operator>>(std::istream& in, Fraction& fraction)
{
    int numerator, denominator;
    in >> numerator;
    if(!in.fail())
        in >> denominator;
    else {
        throw std::runtime_error("Sorry, wrong input, only integer are allowed!");
    }
    
    if(!in.fail()) {  
        fraction.m_numerator = numerator;  
        if(denominator != 0) {
            fraction.m_denominator = denominator;
        } else {
            throw std::logic_error("The denominator cannot be null!");
        }
    } else {
        throw std::runtime_error("Sorry, wrong input, only integer are allowed!");
    }
  
   return in;
}

int Fraction::greatestCommonDivisor() const
{
    int numerator = m_numerator, denominator = m_denominator, divCounter = 0;
    while(numerator % 2 == 0 && denominator % 2 == 0) {
        numerator   /= 2;
        denominator /= 2;
        divCounter++;
    }
    
    do {
        while(numerator  % 2 == 0)
            numerator /= 2;
        
        if(numerator < denominator)
            std::swap(numerator, denominator);
        
        numerator -= denominator;
    } while(numerator != 0);
    
    return denominator * static_cast<int>( pow(2, divCounter) );
}

Fraction& Fraction::cut()
{
    int gcD = greatestCommonDivisor();
    if(gcD != 1) {
        m_numerator   /= gcD;
        m_denominator /= gcD;
    }
    return *this;
}

int main()
{
    Fraction one(2,3);
    std::cout << one << "\n";
    Fraction two(3,3);
    std::cout << two << "\n";
    Fraction third = two / one;
    std::cout << third << "\n";
    std::cout << third.cut() << "\n";
    Fraction fourth = one + two;
    std::cout << fourth << "\n";
    std::cout << fourth.cut() << "\n";
    std::cout << (Fraction(8,9) == Fraction(16,18)) << "\n";
    std::cout << (Fraction(8,9) < Fraction(16,18)) << "\n";
    std::cout << Fraction(1,2).reciprocalValue() << "\n";
    return 0;
}


--
Wer früher stirbt ist länger tot.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
22.12.2003, 15:24 Uhr
virtual
Sexiest Bit alive
(Operator)


Ich habs ehrlich gesagt nicht genau angeschaut, aber mein erster Einwand wäre: Warum kein Template? cut würde ich shorten nennen.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
22.12.2003, 16:18 Uhr
(un)wissender
Niveauwart


Hm, macht den hier ein Template sinn?
Brüche bestehen doch immer aus ganze Zahlen.
Macht ein Bruch aus floats sinn?

ok, shorten dann, danke!
--
Wer früher stirbt ist länger tot.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
22.12.2003, 16:18 Uhr
(un)wissender
Niveauwart


Oh, ich kann es nicht mehr editieren, schade...
--
Wer früher stirbt ist länger tot.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
22.12.2003, 16:43 Uhr
virtual
Sexiest Bit alive
(Operator)


Ein Template macht IMHO shon sinn: Ich könnte ja nächste Woche mal auf die Idee kommen, eine Klasse zu schreiben, die mit belieg langen Ganzzahlen klar kommt... (Natürlich komme ich nicht auf die Idee, weil es die Schon gibt)
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
22.12.2003, 16:51 Uhr
(un)wissender
Niveauwart


Hm, ok, das ist schon ein Argument.
Es scheint wirklich schwer zu sein, etwas zu machen, was es nicht schon gibt...nicht das ich glauben würde hier etwas neues zu machen.
--
Wer früher stirbt ist länger tot.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
22.12.2003, 22:40 Uhr
FloSoft
Medialer Over-Flow
(Administrator)


templates funzen nur unter VC z.b nicht richtig, so ists "portabler"
--
class God : public ChuckNorris { };
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
22.12.2003, 22:49 Uhr
0xdeadbeef
Gott
(Operator)


Nein, nein, ich muss mich zurückhalten...nein, nein, nein, heute kein MS-Bashing mehr...nein, aber das ist so eine tolle Vorlage...nein, nein, AAARGH!!!
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
22.12.2003, 22:53 Uhr
virtual
Sexiest Bit alive
(Operator)


Also so ein Template der Form

C++:
template<typename N, typename D>
class fraction
{
...


wird der VC 6 problos schlucken können ist auch völlig ausreichend. Beim VC 7 gehts eh.

(PS: Nein, ich bin nicht MS Protagonist geworden, glaube aber fest, daß die beste Werbung für MS unberechtigte Kritik an deren Produkten ist)
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
23.12.2003, 08:32 Uhr
FloSoft
Medialer Over-Flow
(Administrator)


naja, die zipstream-templates hat der vc z.b nicht geschluckt....
--
class God : public ChuckNorris { };
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 < [ 2 ]     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: