Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Invariants teil 2

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 <
000
23.03.2006, 10:05 Uhr
ref



Der Code:

C++:
// Invariants
#define DEBUG
#define SHOW_INVARIANTS
#include <iostream>
#include <string.h>

#ifndef DEBUG
#define ASSERT(x)
#else
#define ASSERT(x) \
     if (! (x)) \
     { \
         std::cout << "FEHLER!! Annahme " << #x << " nicht zutreffend\n"; \
         std::cout << " in Zeile " << __LINE__  << "\n"; \
         std::cout << " in Datei " << __FILE__ << "\n";  \
     }
#endif

class String
{
public:
     // Konstruktoren
     String();
     String(const char *const);
     String(const String &);
     ~String();

     char & operator[](int offset);
     char operator[](int offset) const;

     String & operator= (const String &);
     int GetLen()const { return itsLen; }
     const char * GetString() const { return itsString; }
     bool Invariants() const;

private:
     String (int);         // Privater Konstruktor
     char * itsString;
     unsigned short itsLen;
};

// Standardkonstruktor erzeugt String von 0 Bytes Länge
String::String()
{
     itsString = new char[1];
     itsString[0] = '\0';
     itsLen=0;
     ASSERT(Invariants());
}

// Privater (Hilfs-) Konstruktor, nur von Klassen-
// methoden für das Erzeugen eines neuen Strings der
// erforderlichen Größe verwendet.  Mit Null gefüllt.
String::String(int len)
{
     itsString = new char[len+1];
     for (int i = 0; i<=len; i++)
         itsString[i] = '\0';
     itsLen=len;
     ASSERT(Invariants());
}

// Konvertiert ein Zeichen-Array in einen String
String::String(const char * const cString)
{
     itsLen = strlen(cString);
     itsString = new char[itsLen+1];
     for (int i = 0; i<itsLen; i++)
         itsString[i] = cString[i];
     itsString[itsLen]='\0';
     ASSERT(Invariants());
}

// Kopierkonstruktor
String::String (const String & rhs)
{
     itsLen=rhs.GetLen();
     itsString = new char[itsLen+1];
     for (int i = 0; i<itsLen;i++)
         itsString[i] = rhs[i];
     itsString[itsLen] = '\0';
     ASSERT(Invariants());
}

// Destruktor, gibt reservierten Speicher frei
String::~String ()
{
     ASSERT(Invariants());
     delete [] itsString;
     itsLen = 0;
}

// Gleich-Operator, gibt vorhandenen Speicher frei,
// kopiert dann String und Größe
String& String::operator=(const String & rhs)
{
     ASSERT(Invariants());
     if (this == &rhs)
         return *this;
     delete [] itsString;
     itsLen=rhs.GetLen();
     itsString = new char[itsLen+1];
     for (int i = 0; i<itsLen;i++)
         itsString[i] = rhs[i];
     itsString[itsLen] = '\0';
     ASSERT(Invariants());
     return *this;
}

// Nicht-konstanter Offset-Operator, gibt Referenz
// auf Zeichen zurück, das sich damit ändern
// lässt!
char & String::operator[](int offset)
{
     ASSERT(Invariants());
     if (offset > itsLen)
         return itsString[itsLen-1];
     else
         return itsString[offset];
     ASSERT(Invariants());
}

// Konstanter Offset-Operator für konstante
// Objekte (siehe Kopierkonstruktor!)
char String::operator[](int offset) const
{
     ASSERT(Invariants());
     if (offset > itsLen)
         return itsString[itsLen-1];
     else
         return itsString[offset];
     ASSERT(Invariants());
}

// Sicherstellen, dass der String eine bestimmte Länge hat, oder
// der Zeiger ist NULL und die Länge ist null.
bool String::Invariants() const
{
#ifdef SHOW_INVARIANTS
     std::cout << " String OK ";
#endif
     return ( (itsLen && itsString) || (!itsLen && !itsString) );
}

class Animal
{
public:
     Animal():itsAge(1),itsName("John Q. Animal")
         {ASSERT(Invariants());}
     Animal(int, const String&);
     ~Animal(){}
     int GetAge() { ASSERT(Invariants()); return itsAge;}
     void SetAge(int Age)
         {
             ASSERT(Invariants());
             itsAge = Age;
             ASSERT(Invariants());
         }
     String& GetName() { ASSERT(Invariants()); return itsName;  }
     void SetName(const String& name)
         {
             ASSERT(Invariants());
             itsName = name;
             ASSERT(Invariants());
         }
     bool Invariants();
private:
     int itsAge;
     String itsName;
};

Animal::Animal(int age, const String& name):
itsAge(age),
itsName(name)
{
     ASSERT(Invariants());
}

bool Animal::Invariants()
{
#ifdef SHOW_INVARIANTS
     std::cout << " Animal OK ";
#endif
     return (itsAge > 0 && itsName.GetLen());
}

int main()
{
     Animal sparky(5,"Sparky");
     std::cout << "\n" << sparky.GetName().GetString() << " ist ";
     std::cout << sparky.GetAge() << " Jahre alt.";
     sparky.SetAge(8);
     std::cout << "\n" << sparky.GetName().GetString() << " ist ";
     std::cout << sparky.GetAge() << " Jahre alt.";
    return 0;
}





verlauf:

string const char *const konstruktor
String OK
string const char *const konstruktor ende

kopiekonstruktor

char string[] operator const start
String OK
zurueck

char string[] operator const start
String OK
zurueck

char string[] operator const start
String OK
zurueck

char string[] operator const start
String OK
zurueck

char string[] operator const start
String OK
zurueck

char string[] operator const start
String OK
zurueck
String OK

kopiekonstruktor ende

Animal konstruktor2
Animal OK
Animal konstruktor2 ende


stringdestruktor
String OK
stringdestruktor ende

string&getname start
Animal OK
string&getname ende

Sparky ist
Animalgetage
Animal OK
Animalgetage ende
5 Jahre alt.
voidsetage start
Animal OK Animal OK
voidsetage ende

string&getname start
Animal OK
string&getname ende

Sparky ist
Animalgetage
Animal OK
Animalgetage ende
8 Jahre alt.

stringdestruktor
String OK
stringdestruktor ende

der frage:
scauen wir erstmal main() ,da befindet:




C++:
Animal sparky(5,"Sparky");




zu animal-konstruktor zuerst geht nicht:

C++:
Animal::Animal(int age, const String& name):
itsAge(age),
itsName(name)
{
     ASSERT(Invariants());
}




es muss const String& name behandelt werden .. das führt zu string konstruktor
es hat aber beide aufgerufen:



C++:
String(const char *const);
String(const String &);



ich bin der meinung dass nur der zweite passt also(kopiekonstruktor)
die frage warum der erste auch statt gefunden ?????
--
Man kann ein Problem nicht mit der gleichen Denkweise lösen, mit der es erschaffen wurde. (Albert Einstein)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
23.03.2006, 10:21 Uhr
FloSoft
Medialer Over-Flow
(Administrator)


ganz einfach, zuerst wird bei dem aufruf von


C++:
Animal::Animal(int age, const String& name)



der String-Konstruktor


C++:
String(const char *const)




aufgerufen, dann für


C++:
itsName(name)




der Kopierkonstruktor


C++:
String(const String &)


--
class God : public ChuckNorris { };
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
23.03.2006, 11:58 Uhr
ref



Jaa klaar ,
itsAge(age),
itsName(name)


warum habe ich daran nicht gedacht, danke.
--
Man kann ein Problem nicht mit der gleichen Denkweise lösen, mit der es erschaffen wurde. (Albert Einstein)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
23.03.2006, 15:10 Uhr
ref



Ich habe andere frage .. in string konstruktor gibt es: itsString[i] = cString[i];


C++:
String::String(const char * const cString)
{
     itsLen = strlen(cString);
     itsString = new char[itsLen+1];
     for (int i = 0; i<itsLen; i++)
         itsString[i] = cString[i]; // keine operator wird aufgerufen
     itsString[itsLen]='\0';
     ASSERT(Invariants());
}




und in kopiekopiekonstruktor ähnliches : itsString[i] = rhs[i];

C++:
String::String (const String & rhs)
{
     itsLen=rhs.GetLen();
     itsString = new char[itsLen+1];
     for (int i = 0; i<itsLen;i++)
         itsString[i] = rhs[i]; // hier wird char operator[](int offset) const; aufgerufen
     itsString[itsLen] = '\0';
     ASSERT(Invariants());
}




aber in kopiekonstruktor wird itsString[i] = rhs[i] ; den operator : char operator[](int offset) const; aufrufen .
warum also wurde den operator beim itsString[i] = rhs[i] ; in kopiekonstuktor aufgerufen und vorher nicht mit itsString[i] = cString[i]; in string-konstruktor aufgerufen?
hatte es mit rhs zu tun? ,da rhs ist ein adresse oder referenz ,oder gibt es andere grunde
wie funktionieren operatoren??????
--
Man kann ein Problem nicht mit der gleichen Denkweise lösen, mit der es erschaffen wurde. (Albert Einstein)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
23.03.2006, 20:53 Uhr
FloSoft
Medialer Over-Flow
(Administrator)


ist ja auch eine einfache zuweisung eines basistypen, keine konstruktorsache
--
class God : public ChuckNorris { };
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ 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: