// Werken met breuken in C++ ... destructor

#include <iostream>
#include <cassert>
using namespace std;

// Class declaratie:

class Breuk {
public:
	// Class interface.
	// Vertelt wat je met een object van de class kunt doen.
	Breuk();
	Breuk(int t);
	Breuk(int t, int n);
	~Breuk();
	int teller() const;
	int noemer() const;
	void plus(Breuk b);
	void abs();
//	...
//	Er zijn nog veel uitbreidingen mogelijk.
//	...
private:
	// Class implementatie.
	// Vertelt wat je nodig hebt om een object van de class te maken.
	// Dit is voor gebruikers van de class niet van belang.
	int boven;
	int onder;
	void normaliseer();
};

// Hulpfunctie: bepaald de grootste gemene deler.

int ggd(int n, int m) {
	if (n==0) return m;
	if (m==0) return n;
	if (n<0) n=-n;
	if (m<0) m=-m;
	while (m!=n)
		if (n>m) n-=m;
		else m-=n;
	return n;
}

// Class definitie:
// Vertelt hoe de memberfuncties van de class geïmplenteerd zijn.
// Dit is voor gebruikers van de class niet van belang.

Breuk::Breuk(): boven(0), onder(1) {
}

Breuk::Breuk(int t): boven(t), onder(1) {
}

Breuk::Breuk(int t, int n): boven(t), onder(n) {
	normaliseer();
}

Breuk::~Breuk() {
	cout<<"Een breuk met de waarde "<<boven<<"/"<<onder<<" is verwijderd uit het geheugen."<<endl;
	cout<<"Druk op enter om verder te gaan..."<<endl;
   	cin.get();
}

int Breuk::teller() const {
	return boven;
}

int Breuk::noemer() const {
	return onder;
}

void Breuk::plus(Breuk b) {
	boven=boven*b.onder + onder*b.boven;
	onder*=b.onder;
	normaliseer();
}

void Breuk::abs() {
	if (boven<0) boven=-boven;
}

void Breuk::normaliseer() {
	assert(onder!=0);
	if (onder<0) {
		onder=-onder;
		boven=-boven;
	}
	int d(ggd(boven,onder));
	boven/=d;
	onder/=d;
}

// Hoofdprogramma:

int main() {
	Breuk b1(4);
	cout<<"b1(4) ==> "<<b1.teller()<<'/'<<b1.noemer()<<endl;
	Breuk b2(23, -5);
	cout<<"b2(23, -5) ==> "<<b2.teller()<<'/'<<b2.noemer()<<endl;
	Breuk b3(b2);
	cout<<"b3(b2) ==> "<<b3.teller()<<'/'<<b3.noemer()<<endl;
	b3.abs();
	cout<<"b3.abs() ==> "<<b3.teller()<<'/'<<b3.noemer()<<endl;
	b3=b2;
	cout<<"b3=b2 ==> "<<b3.teller()<<'/'<<b3.noemer()<<endl;
	b3.plus(5);
	cout<<"b3.plus(5) ==> "<<b3.teller()<<'/'<<b3.noemer()<<endl;

	const Breuk halve(1,2);
	cout<<"halve ==> "<<halve.teller()<<'/'<<halve.noemer()<<endl;

//	halve=b3;
//	[C++ Error Borland C++ Builder]:   Cannot modify a const object
//	[C++ Error gcc]:                   passing `const Breuk' as `this' argument of `Breuk& Breuk::operator=(const Breuk&)' discards qualifiers
//	[C++ Error Microsoft Visual C++]:  binary '=' : no operator found which takes a left-hand operand of type 'const Breuk' (or there is no acceptable conversion)

//	halve.plus(b3);
//	[C++ Warning Borland C++ Builder]: Non-const function Breuk::plus(const Breuk &) called for const object
//	(This is an error, but was reduced to a warning to give existing programs a chance to work.)
//	[C++ Error gcc]:                   passing `const Breuk' as `this' argument of `void Breuk::plus(Breuk)' discards qualifiers 
//	[C++ Error Microsoft Visual C++]:  'Breuk::plus' : cannot convert 'this' pointer from 'const Breuk' to 'Breuk &' (Conversion loses qualifiers)

	b3=halve;
	cout<<"b3=halve ==> "<<b3.teller()<<'/'<<b3.noemer()<<endl;

	cin.get();
	return 0;
}
