TheHawk
08-04-2007, 16:34
Habe von einer Lern-CD folgendes Programm herunter und auch schon leicht abgeändert, aber mein Compiler spuckt mir noch immer Probleme aus. Compiler ist MinGW für Windows. Compilieren tu ich mit dem Befehl "g++ -c Budget5_1.cpp".
Die Fehlermeldung
Budget5_1.cpp: In member function `void Account::addToList(Account*&)':
Budget5_1.cpp:96: error: name lookup of `pA' changed for new ISO `for' scoping
Budget5_1.cpp:93: error: using obsolete binding at `pA'
Das Programm
//BUDGET5.1c - Diese version splittet die verkettet Liste
// in zwei Teile. Dies ist die Lösung für Aufgabe 1.c
#include <iostream> // alt: #include <iostream.h>
#include <stdlib.h>
#include <ctype.h>
using namespace std; // Diese Zeile fehlte überhaupt.
//Account - diese abstrakte Klasse umfaßt Eigenschaften
// beider Kontotypen, Giro- und Sparkonto: es fehlt
// das Konzept withdrawal( ), das für beide unter-
// schiedlich ist.
class Account
{
protected:
Account(Account &c)
{
cout << "Konto erstellen\n";
}
//diese Funktion fügt der Liste, auf die das Argument der
//Funktion zeigt, ein Objekt hinzu
void addToList(Account * &pFirst); //Note 1
public:
Account(unsigned accNo, float initialBalance = 0.0F);
//Zugriffsfunktionen
int accountNo( )
{
return accountNumber;
}
float acntBalance( )
{
return balance;
}
static int noAccounts( )
{
return count;
}
//Transactionsfunktionen
void deposit(float amount)
{
balance += amount;
}
virtual void withdrawal(float amount) = 0;
//Anzeigefunktionen
void display( )
{
cout << "Konto " << accountNumber
<< " = " << balance
<< "\n";
}
//die folgenden Funktionen werden rein virtuell
Account *next( )
{
return pNext;
}
protected:
static int count; //Anzahl der Konten
unsigned accountNumber;
float balance;
//pNext ist noch im Account, aber pFirst //Note 2
//ist jetzt den Unterklassen zugeordnet
Account *pNext;
};
int Account::count = 0;
Account::Account(unsigned accNo, float initialBalance)
{
accountNumber = accNo;
balance = initialBalance;
count++;
}
//addToList - durch die Übernahme von pFirst als Argument kann
// addToList( ) von Checking und von Savings
// aufgerufen werden
void Account::addToList(Account * &pFirst)
{
//das entsteht aus dem Konstruktor für Account
if (pFirst == 0)
{
pFirst = this; //leere Liste; zum ersten machen
}
else { //Liste nicht leer; nach letztem
//Eintrag in der Liste suchen
for (Account *pA = pFirst; pA->pNext; pA = pA->pNext)
{
}
pA->pNext = this; //zum Ende gehen
}
pNext = 0; //wir sind immer die Letzten
}
//Checking - diese Klasse enthält Eigenschaften, die für Giro-
// konten eindeutig sind. Nicht mehr viel, was?
class Checking : public Account
{
public:
//hier ist der Konstruktor inline definiert
Checking(unsigned accNo, float initialBalance = 0.0F) :
Account(accNo, initialBalance)
{
addToList(Checking::pFirst); //Note 3
}
//rein virtuelle Funktionen überladen
virtual void withdrawal(float amount);
//erstes Objekt der Girokonten-Liste zurückgeben
static Account* first( ) //Note 4
{
return (Account*)Checking::pFirst;
}
protected:
static Account* pFirst;
};
Account *Checking::pFirst = 0;
void Checking::withdrawal(float amount)
{
if (balance < amount )
{
cout << "Keine ausreichende Deckung: Saldo " << balance
<< ", Scheck " << amount
<< "\n";
}
else
{
balance -= amount;
//wenn der Saldo zu niedrig liegt, Gebühren ändern
if (balance < 500.00F)
{
balance -= 0.20F;
}
}
}
//Savings - dasselbe wie bei Checking, außer das es hier auch ein
// eindeutiges Datenelement gibt
class Savings : public Account
{
public:
//hier ist der Konstruktor als separate Funktion definiert,
//nur um Ihnen den Unterschied zu verdeutlichen
Savings(unsigned accNo, float initialBalance = 0.0F) :
Account(accNo, initialBalance)
{
noWithdrawals = 0;
addToList(Savings::pFirst);
}
//Transaktionsfunktionen
virtual void withdrawal(float amount);
static Account* first( )
{
return (Account*)Savings::pFirst;
}
protected:
int noWithdrawals;
static Account *pFirst;
};
Account* Savings::pFirst = 0;
void Savings::withdrawal(float amount)
{
if (balance < amount)
{
cout << "Keine ausreichende Deckung: Saldo " << balance
<< ", Abhebung " << amount
<< "\n";
}
else
{
if (++noWithdrawals > 1)
{
balance -= 5.00F;
}
balance -= amount;
}
}
//Prototypendeklarationen
unsigned getAccntNo( );
void process(Account &account);
void outOfMemory( );
int main( );
//main - Einzahlungen und Auszahlungen gesamt
int main( )
{
/*Schleife bis jemand 'X' or 'x' einfügt*/
Account *pA;
char accountType; //S or C
unsigned keepLooping = 1;
while (keepLooping)
{
cout << "Geben Sie S für Sparkonto, "
"C für Girokonto oder X zum Beenden ein\n";
cin >> accountType;
switch (accountType)
{
case 'c':
case 'C':
pA = new Checking(getAccntNo( ));
if (pA == 0)
{
outOfMemory( );
}
process(*pA);
break;
case 's':
case 'S':
pA = new Savings(getAccntNo( ));
if (pA == 0)
{
outOfMemory( );
}
process(*pA);
break;
case 'x':
case 'X':
keepLooping = 0;
break;
default:
cout << "Wie war das?\n";
}
}
//Gesamtsummen anzeigen //Note 5
float subTotal = 0.0F;
float total = 0.0F;
cout << "Kontensummen:\n";
//jetzt müssen wir die Listen separat anzeigen
for (pA = Checking::first( ); pA; pA = pA->next( ))
{
pA->display( );
subTotal += pA->acntBalance( );
}
cout << "Gesamtsumme aller Girokonten = " << subTotal
<< "\n";
total += subTotal;
//dasselbe für die Sparkonten
subTotal = 0.0F;
for (pA = Savings::first( ); pA; pA = pA->next( ))
{
pA->display( );
subTotal += pA->acntBalance( );
}
cout << "Gesamtsumme aller Sparkonten = " << subTotal
<< "\n";
total += subTotal;
cout << "Gesamtwert aller Konten = " << total
<< "\n";
return 0;
}
//getAccntNo - die eingegebene Kontonummer zurückgeben
unsigned getAccntNo( )
{
unsigned accntNo;
cout << "Geben Sie die Kontonummer ein:";
cin >> accntNo;
return accntNo;
}
//process(Account) - Daten für das Konto eingeben*/
void process(Account &account)
{
cout << "Positive Zahl für Einzahlung,\n"
"negative für Abhebung, 0 zum Beenden";
float transaction;
do
{
cout << ":";
cin >> transaction;
//Einzahlung
if (transaction > 0.0F)
{
account.deposit(transaction);
}
//Abhebung
if (transaction < 0.0F) {
account.withdrawal(-transaction);
}
} while (transaction != 0.0F);
}
//outOfMemory - Fehler: kein Speicher; Beenden
void outOfMemory( )
{
cout << "Kein Speicher\n";
abort( );
}
Die Fehlermeldung
Budget5_1.cpp: In member function `void Account::addToList(Account*&)':
Budget5_1.cpp:96: error: name lookup of `pA' changed for new ISO `for' scoping
Budget5_1.cpp:93: error: using obsolete binding at `pA'
Das Programm
//BUDGET5.1c - Diese version splittet die verkettet Liste
// in zwei Teile. Dies ist die Lösung für Aufgabe 1.c
#include <iostream> // alt: #include <iostream.h>
#include <stdlib.h>
#include <ctype.h>
using namespace std; // Diese Zeile fehlte überhaupt.
//Account - diese abstrakte Klasse umfaßt Eigenschaften
// beider Kontotypen, Giro- und Sparkonto: es fehlt
// das Konzept withdrawal( ), das für beide unter-
// schiedlich ist.
class Account
{
protected:
Account(Account &c)
{
cout << "Konto erstellen\n";
}
//diese Funktion fügt der Liste, auf die das Argument der
//Funktion zeigt, ein Objekt hinzu
void addToList(Account * &pFirst); //Note 1
public:
Account(unsigned accNo, float initialBalance = 0.0F);
//Zugriffsfunktionen
int accountNo( )
{
return accountNumber;
}
float acntBalance( )
{
return balance;
}
static int noAccounts( )
{
return count;
}
//Transactionsfunktionen
void deposit(float amount)
{
balance += amount;
}
virtual void withdrawal(float amount) = 0;
//Anzeigefunktionen
void display( )
{
cout << "Konto " << accountNumber
<< " = " << balance
<< "\n";
}
//die folgenden Funktionen werden rein virtuell
Account *next( )
{
return pNext;
}
protected:
static int count; //Anzahl der Konten
unsigned accountNumber;
float balance;
//pNext ist noch im Account, aber pFirst //Note 2
//ist jetzt den Unterklassen zugeordnet
Account *pNext;
};
int Account::count = 0;
Account::Account(unsigned accNo, float initialBalance)
{
accountNumber = accNo;
balance = initialBalance;
count++;
}
//addToList - durch die Übernahme von pFirst als Argument kann
// addToList( ) von Checking und von Savings
// aufgerufen werden
void Account::addToList(Account * &pFirst)
{
//das entsteht aus dem Konstruktor für Account
if (pFirst == 0)
{
pFirst = this; //leere Liste; zum ersten machen
}
else { //Liste nicht leer; nach letztem
//Eintrag in der Liste suchen
for (Account *pA = pFirst; pA->pNext; pA = pA->pNext)
{
}
pA->pNext = this; //zum Ende gehen
}
pNext = 0; //wir sind immer die Letzten
}
//Checking - diese Klasse enthält Eigenschaften, die für Giro-
// konten eindeutig sind. Nicht mehr viel, was?
class Checking : public Account
{
public:
//hier ist der Konstruktor inline definiert
Checking(unsigned accNo, float initialBalance = 0.0F) :
Account(accNo, initialBalance)
{
addToList(Checking::pFirst); //Note 3
}
//rein virtuelle Funktionen überladen
virtual void withdrawal(float amount);
//erstes Objekt der Girokonten-Liste zurückgeben
static Account* first( ) //Note 4
{
return (Account*)Checking::pFirst;
}
protected:
static Account* pFirst;
};
Account *Checking::pFirst = 0;
void Checking::withdrawal(float amount)
{
if (balance < amount )
{
cout << "Keine ausreichende Deckung: Saldo " << balance
<< ", Scheck " << amount
<< "\n";
}
else
{
balance -= amount;
//wenn der Saldo zu niedrig liegt, Gebühren ändern
if (balance < 500.00F)
{
balance -= 0.20F;
}
}
}
//Savings - dasselbe wie bei Checking, außer das es hier auch ein
// eindeutiges Datenelement gibt
class Savings : public Account
{
public:
//hier ist der Konstruktor als separate Funktion definiert,
//nur um Ihnen den Unterschied zu verdeutlichen
Savings(unsigned accNo, float initialBalance = 0.0F) :
Account(accNo, initialBalance)
{
noWithdrawals = 0;
addToList(Savings::pFirst);
}
//Transaktionsfunktionen
virtual void withdrawal(float amount);
static Account* first( )
{
return (Account*)Savings::pFirst;
}
protected:
int noWithdrawals;
static Account *pFirst;
};
Account* Savings::pFirst = 0;
void Savings::withdrawal(float amount)
{
if (balance < amount)
{
cout << "Keine ausreichende Deckung: Saldo " << balance
<< ", Abhebung " << amount
<< "\n";
}
else
{
if (++noWithdrawals > 1)
{
balance -= 5.00F;
}
balance -= amount;
}
}
//Prototypendeklarationen
unsigned getAccntNo( );
void process(Account &account);
void outOfMemory( );
int main( );
//main - Einzahlungen und Auszahlungen gesamt
int main( )
{
/*Schleife bis jemand 'X' or 'x' einfügt*/
Account *pA;
char accountType; //S or C
unsigned keepLooping = 1;
while (keepLooping)
{
cout << "Geben Sie S für Sparkonto, "
"C für Girokonto oder X zum Beenden ein\n";
cin >> accountType;
switch (accountType)
{
case 'c':
case 'C':
pA = new Checking(getAccntNo( ));
if (pA == 0)
{
outOfMemory( );
}
process(*pA);
break;
case 's':
case 'S':
pA = new Savings(getAccntNo( ));
if (pA == 0)
{
outOfMemory( );
}
process(*pA);
break;
case 'x':
case 'X':
keepLooping = 0;
break;
default:
cout << "Wie war das?\n";
}
}
//Gesamtsummen anzeigen //Note 5
float subTotal = 0.0F;
float total = 0.0F;
cout << "Kontensummen:\n";
//jetzt müssen wir die Listen separat anzeigen
for (pA = Checking::first( ); pA; pA = pA->next( ))
{
pA->display( );
subTotal += pA->acntBalance( );
}
cout << "Gesamtsumme aller Girokonten = " << subTotal
<< "\n";
total += subTotal;
//dasselbe für die Sparkonten
subTotal = 0.0F;
for (pA = Savings::first( ); pA; pA = pA->next( ))
{
pA->display( );
subTotal += pA->acntBalance( );
}
cout << "Gesamtsumme aller Sparkonten = " << subTotal
<< "\n";
total += subTotal;
cout << "Gesamtwert aller Konten = " << total
<< "\n";
return 0;
}
//getAccntNo - die eingegebene Kontonummer zurückgeben
unsigned getAccntNo( )
{
unsigned accntNo;
cout << "Geben Sie die Kontonummer ein:";
cin >> accntNo;
return accntNo;
}
//process(Account) - Daten für das Konto eingeben*/
void process(Account &account)
{
cout << "Positive Zahl für Einzahlung,\n"
"negative für Abhebung, 0 zum Beenden";
float transaction;
do
{
cout << ":";
cin >> transaction;
//Einzahlung
if (transaction > 0.0F)
{
account.deposit(transaction);
}
//Abhebung
if (transaction < 0.0F) {
account.withdrawal(-transaction);
}
} while (transaction != 0.0F);
}
//outOfMemory - Fehler: kein Speicher; Beenden
void outOfMemory( )
{
cout << "Kein Speicher\n";
abort( );
}