Willkommen ~Gast!
Registrieren || Einloggen || Hilfe/FAQ || Staff
Probleme mit der Registrierung im Forum? Melde dich unter registerEin Bild.
Autor Beitrag
000
21.08.2001, 15:56
Hanky



moin,

eine kleine Frage..
angenomme ich code sowas wie
#define BLABLA 13
#define BLAANDBLUB 13
,
ist BLABLA und BLAANDBLUB dann was anders?

also z.B. bei einer if Abfrage..

--

hankYs Page

zum Seitenanfang zum Seitenende Profil || Suche
001
21.08.2001, 16:04
Hellfire



Vor dem Compilen werden alle Codestellen, wo BLABLA und BLAANDBLUB steht durch 13 ersetzt. Also bei ner if Abfrage ist es relativ egal, was du abfragst, da beide Makros für den selben Wert stehen.

--


Dieser Beitrag wurde am 21.08.2001 um 16:04 von Hellfire bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
002
21.08.2001, 18:11
apfelkorn



der Hauptgrund, warum man #define's verwendet ist, dass es übersichtlicher wirkt für den Programmierer... Im Endeffekt könntest du z.b. statt:

#define BLUBBER 1
#define NOTBLUBBER 2

if (flags==BLUBBER)
StartPumpingAirIntoWhirlPool();
else if (flags==NOTBLUBBER)
StopPumpingAirIntoWhirlPool();

auch:

if (flags==1)
StartPumpingAirIntoWhirlPool();
else if (flags==2)
StopPumpingAirIntoWhirlPool();

schreiben. Das untere ist zwar kürzer, aber was ist übersichtlicher? Weißt du z.b. nach 1 std. programmieren noch, ob BLUBBER 1 oder 2 ist? Der Compiler weiß es, und setzt daher auch alle #defines ein. Also würde für den Compiler der zu Compilierende Code vom ersten Beispiel für den Compiler wie das untere aussehen.

--


Dieser Beitrag wurde am 21.08.2001 um 18:13 von apfelkorn bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
003
21.08.2001, 18:21
Gollum



Zum Festlegen von konstanten Zahlenwerten sollte man aber const verwenden (vorrausgesetzt du kompilierst mit einem c++ kompiler)...

also statt
#define BLABLA 13
#define BLAANDBLUB 13
schreibt man
const int BLABLA =13;
const int BLAANDBLUB=13;

#define's unter c++ nur für makros

--

[url="http://www.thelordoftherings.com/cgi-bin/get-image.pl?ID=alan-lee-058 "]-N/A-[/url]
[url="http://www.microsoft.com/germany/ms/unternehmensinformationen/historie.htm "]Mean cats eat parakeets![/url]

zum Seitenanfang zum Seitenende Profil || Suche
004
21.08.2001, 19:52
Prefect



const ist aber dumm.. da riskierst du nämlich, dass der Compiler/Linker unnötig Speicher für die ganzen consts reservieren.
Außerdem tut es mir irgendwie in der Seele weh *g*

cu,
Prefect

--

Widelands - Gemütliche Aufbaustrategie, Free Software
Noch ein Blog - Lerne, wie die Welt wirklich ist, aber vergiss niemals, wie sie sein sollte.

zum Seitenanfang zum Seitenende Profil || Suche
005
21.08.2001, 19:59
TheTinySteini



Vor allem muss man ja bei const auch noch angeben, was für ein Typ das sein soll. Hm, das weiß ich aber oft in dem Moment auch noch gar nicht =)
Und bevor ich da dann wieder was casten darf, nehm ich lieber #define. Sieht auch irgendwie stylischer aus. Das ist überhaupt DAS Argument. Nunja...

--

TheTinySteini
Coder Poke646
"Don't Panic" - Hitchhiker's Guide to the Galaxy

zum Seitenanfang zum Seitenende Profil || Suche
006
21.08.2001, 20:57
Mazze



Was sagt ihr zu enum?

--

BattleTech-MOD:
http://bthl.unitedgaming.net/

zum Seitenanfang zum Seitenende Profil || Suche
007
21.08.2001, 21:31
Gollum



Well. klar schaut define 10000x besser aus :) is halt irgendwie klassisch so :)

Dennoch _sollte_ man in C++ mit const arbeiten. Speicher wird für const werte sicher nicht reserviert, wäre ja auch irgendwo sinnlos :)

Daß man den Typ festlegen muss ist natürlich auch eher positiv, so kann man zB zwischen int und float differenzieren, und dann auch an mit int und float überladene funktionen den auf jeden fall richtigen datenyp weitergeben.
Aber das braucht man wohl nicht sehr oft... meist wird man eh int verwenden
[EDIT]
enum... irgendwie kann ich mich mit der idee nicht ganz anfreunden, auch wenn das sicher ganz praktisch ist, wenn man viele konstanten hat die jeweils nur eins höher sind als die vorige, zb bei irgendwelchen symbolen die die verwendung einer funktion erleichtern sollen...
aber wenn man das nur braucht um zB bei einer engine ein paar parameter zu fixieren zum debugen, dann ist das sinnlos weil die ja nicht aufeinanderfolgen...

aber ganz ehrlich gesagt verwende ich selbst meist #define :)

[/EDIT]

--

[url="http://www.thelordoftherings.com/cgi-bin/get-image.pl?ID=alan-lee-058 "]-N/A-[/url]
[url="http://www.microsoft.com/germany/ms/unternehmensinformationen/historie.htm "]Mean cats eat parakeets![/url]


Dieser Beitrag wurde am 21.08.2001 um 21:43 von Gollum bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
008
21.08.2001, 22:11
TheTinySteini



enum rulez, es muss halt richtig eingesetzt werden. Gerade bei Optionen kann einem enum viel Tipparbeit ersparen.

Überladene Funktionen: naja, is ein Argument, aber dann kann ich zur Not auch noch #define EINEZAHL 10.0 schreiben, oder gar #define EINEZAHL 10.0f, beides wird zur Folge haben, dass er die float-Version nimmt. Obwohl, bei der ersten Variante bin ich mir da nicht ganz sicher.

--

TheTinySteini
Coder Poke646
"Don't Panic" - Hitchhiker's Guide to the Galaxy

zum Seitenanfang zum Seitenende Profil || Suche
009
22.08.2001, 18:59
Kriz



Gollum hat Recht! Man sollte #define nur für Abschnittspräkompilierung verwenden und NICHT für die Definition von Konstanten!!! Die Ausnahme bilden da metaportable Codesegmente, die auf Systemen laufen sollen, die zum Bleistift mit bool, false und true sowie NULL nichts anfangen können. Auf diesen Systemen wäre es angebracht, Code in der Art

Quellcode:#ifndef NULL
#define NULL 0
#endif // NULL

usw. zu implementieren. Späße wie

Quellcode:#define PI = 3.1415927

sind Anfängerkacke und zeugen von sehr schlechtem Programmierstil (und Programmierkenntnissen). Also Konstanten immer so initialisieren:

Quellcode:const double PI = 3.1415927;

Stellen sich jetzt nur noch zwei Fragen: Erstens "Wieso?" und zweitens "Was sind Abschnittspräkompilierungen?". Zu erstens: Richtige Konstanten auf Basis von C++ werden typgeprüft, was #defines definitiv nicht machen (Das gilt übrigens auch für solche Unarten wie Funktionsmakros, von denen zwar abgeraten wird, aber es trotzdem jeder macht =).

Zu zweitens: Die Aufteilung von Klassen in Klassenheader und Klassenquellcode wird am Besten in C++ mit #define geregelt. Da es durchaus vorkommt, daß der Präprozessor viele Headers und Quellcodes während des Kompilierens mehrfach einbinden muß aufgrund der Gesamtstruktur des Quellcodes, kann es je nach Compiler und Code zu Fehlern kommen. Das umgeht man mit der Abschnittspräkompilierung:

Quellcode:// Headerdatei AAA.h
#ifndef AAA_H
#define AAA_H

// Code... (Klassen, enums usw.)

#endif // AAA_H

Der Sinn ist klar: Sobald die Headerdatei AAA.h einmal vom Präprozessor eingebunden worden ist, hat er auch das Makro AAA_H definiert. Sollte im späteren Preprocessing die Header AAA.h nochmals eingebunden werden, so erkennt der Präprozessor, daß das Makro AAA_H existiert und ignoriert allen Code bis zum dazugehörigen #endif. Das war schon die ganze Kunst.

Also, Konstanten immer mit const deklarieren usw. und Makros nur für solche Arbeiten wie oben beschrieben benutzen.

Jaja, ich weiß, die meisten sind faule Säcke und würden mit #define am Liebsten ganze Programme definieren =) Aber so schreibt es das Software Engineering für C++ eben vor und wer gute Arbeit leistet, der wird auch entsprechend belohnt mit wenig Wartung und Debugging...

Cu

--

K:R-I)Z++
"CSS ist cascading style sheets. Und nicht so'n Ranzspiel." - dp
In memory of Voice († 2005/03/30)

zum Seitenanfang zum Seitenende Profil || Suche
010
23.08.2001, 22:07
Hanky



da fragt man nur eine Frage..:D

DANKE LADYS! (das hat eine tiefe männliche Stimme sanft und beruhigend gesatg.. es ist meine Stimmme!)

--

hankYs Page

zum Seitenanfang zum Seitenende Profil || Suche
011
24.08.2001, 18:15
TheTinySteini



Zitat:
#define PI = 3.1415927

Stimmt, das ist "Anfängerkacke und [zeugt] von sehr schlechtem Programmierstil (und Programmierkenntnissen)", denn das "=" muss weg :P

Naja, und sonst: Es ist wirklich nur die Typüberprüfung, die für const spricht. Nix weiter. Und ehrlich gesagt, manchmal suckt Typüberprüfung einfach gewaltig, da hab ich lieber die Flexibilität einer #define-Konstante. Und wenn man den Dingern nen vernünftigen Namen gibt, dann sind Verwechslungen eigentlich sowieso ausgeschlossen. Ich meine, dass man nicht sowas hier machen sollte:
Quellcode:#define PI1 3.141592
#define PI2 "3.141592"
float degrees = 90f;
float rad = degrees * PI2 / 180;

dürfte eigentlich klar sein. Das is absoluter Namens-Dünnpfiff und absolut kein guter Programmierstil. Aber wer macht das schon so, außer vielleicht Microsoft-Programmierer *g* (die haben selber die Ungarische Notation entworfen - naja, einer von denen - trotzdem macht z.B. VBasic bei neuen Steuerelementen immer was der Art TypX, also Label1, Label2, Label3, rah! Delphi is da allerdings auch nicht besser...)

--

TheTinySteini
Coder Poke646
"Don't Panic" - Hitchhiker's Guide to the Galaxy

zum Seitenanfang zum Seitenende Profil || Suche
012
24.08.2001, 18:21
Prefect



Ach Kriz, du unverbesserlicher C++-Moralapostel ;)

#define ist am stylischsten, enum bringt Sinn für so Auswahloptionen. const... naja, im Kontext von const char *GetText() const; schon, aber sonst? Nein danke.
Das ist genauso wie Pass by Reference. Das ist ungefähr die dümmste Idee überhaupt, weil man nicht mehr weiß, wo eine andere Funktion evtl. übergebene Parameter verändert. Nunja.

Ach ja, und const-Variablen können durchaus Speicher belegen, nämlich dann, wenn man irgendwo einen Pointer darauf verwendet.

TTT: Hungarische Notation ist wirklich was feines.

Und was die meisten immer vergessen: Dosis fazit venenum.
Mit riesigen Makro-#defines ist das genauso wie mit gotos. Ab und zu sind gotos SEHR nützlich - Schonmal versucht, ein COM-Programm ohne gotos zu programmieren? Du hast die Wahl zwischen Exceptionhandlern (Weiche von mir, Werk des Teufels), riesigen Fehlerbehandlungsblöcken (80% Fehlerbehandlung, 20% Code) und gotos.

Ach ja, Exceptions sind wirklich was, von dem man die Finger lassen sollte. Schaut euch das Zeug nur mal im Debugger an :|

cu,
Prefect

--

Widelands - Gemütliche Aufbaustrategie, Free Software
Noch ein Blog - Lerne, wie die Welt wirklich ist, aber vergiss niemals, wie sie sein sollte.


Dieser Beitrag wurde am 24.08.2001 um 18:25 von Prefect bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
013
24.08.2001, 19:02
Andy_



Zitat:
Prefect postete

TTT: Hungarische Notation ist wirklich was feines.

Tztztz, Prefi
Wasn Hangarisch? Entweder Ungarische Notation, oder hungarian-notation. ;)

--

42 Es gibt keinen Sinn des Lebens.


Dieser Beitrag wurde am 24.08.2001 um 19:02 von Andy bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
014
24.08.2001, 19:41
Mazze



Hangarisch?
Wo?
Wer hat das geschrieben? *g*

--

BattleTech-MOD:
http://bthl.unitedgaming.net/

zum Seitenanfang zum Seitenende Profil || Suche
015
26.08.2001, 17:34
Kriz



@TTT: Jo, das = muß weg :)

@Prefi:

Quellcode:const char *GetText() const;

Soviel ich weiß, regelt das abschließende const bereits die Tatsache, daß der Rückgabewert konstant ist. Kann aber sein, daß das vordere const noch ein Relikt aus der C-Zeit ist :-? Hehehe, da fällt mir wieder ein, wie ich einem Spack versucht hab zu erklären, warum Get-Methoden soweit wie möglich als const deklariert werden sollten (in Bezug auf Kopierkonstruktoren). Der Sack hat das doch net begriffen, was ich von ihm wollte... Der hatte brav weiter seinen Kopierkonstruktor nach der Methode

Quellcode:CIrgendwas(CIrgendwas objekt) {}

gebastelt und sich gewundert, wieso in Bruchteilen von Sekunden der verfügbare Hauptspeicher übergelaufen war (muhahaha)...

--

K:R-I)Z++
"CSS ist cascading style sheets. Und nicht so'n Ranzspiel." - dp
In memory of Voice († 2005/03/30)

zum Seitenanfang zum Seitenende Profil || Suche
016
28.08.2001, 20:17
Prefect



Das mit dem Hauptspeicheüberlauf dürfte aber nicht am const, sondern am Pass by Value (statt Pass by Reference) liegen...

---
const char *GetText() const;

ist die Deklaration einer Methode in einer Klasse. Das erste const besagt, dass der Aufrufer den Datenbereich, auf den der zurückgegebene Pointer zeigt, nicht verändern darf.
Das zweite const besagt, dass GetText() den this-Pointer nicht verändert. Mit anderen Worten, GetText() verändert keine Membervariablen der Klasse. Bei nicht-Methoden bringt ein zweites const natürlich keinen Sinn. Ach ja, es ist durchaus eine Methode denkbar, die ein nicht-const zurückgibt, selbst aber const ist. So z.B. folgende Methode:

char *Foo::DupText() const
{
return strdup(m_pszText);
}

cu,
Prefect

--

Widelands - Gemütliche Aufbaustrategie, Free Software
Noch ein Blog - Lerne, wie die Welt wirklich ist, aber vergiss niemals, wie sie sein sollte.

zum Seitenanfang zum Seitenende Profil || Suche
017
29.08.2001, 01:12
Kriz



Das zweite const besagte eigentlich, daß wenn das Objekt konstant ist, daß auch nur dann solche Methoden aufgerufen werden dürfen, die als const deklariert worden sind. Ansonsten hat man auf diese Funktionen keinen Zugriff von außen, selbst wenn sie public sind! Das erste const ist so wie Prefi es gesagt hat =)

*** Für den Rest der gottlosen Nicht-C++er ***

In Bezug auf den Kopierkonstruktor ist eine konstante Methode lebenswichtig, denn man übergibt ein Referenz der eigenen Klasse stets konstant an den Kopierkonstruktor der eigenen Klassen, sonst knallt es (wie weiter oben gesagt) sofort den verfügbaren Hauptspeicher zu:

Quellcode:CFoo(const CFoo &bar {...} // korrekt

CFoo(CFoo bar) {...} // Bitterböse Falle !!!

Ohne Referenz ruft sich der Standardkonstruktor von CFoo auf, denn das simple bar ist eine neue Instanz von CFoo. Bei der Übergabe der Kopierwerte erzeugt CFoo dann (infolge seines eigenen Kopierkonstruktors) wiederum eine neue Instanz von CFoo, diese wiederum und diese wiederum usw. Es ensteht eine Rekursion, die den RAM vollknallt.

Also verwendet man eine Referenz auf die eigene Klasse (einen impliziten Zeiger also). Dummerweise kann man aber so die Inhalte des Arguments (der zu kopierenden Klassenreferenz nämlich), verändern und das ist böse böse... Also macht man eine konstante Referenz (konstantes Objekt).

Dieses konstante Objekt aber nur über konstante Methoden aufgerufen werden. Nichtkonstante Methoden erzeugen beim Aufrufen Fehlermeldungen. Daher erhält eine konstante Methode am Ende das const.

Man kann aber auch Elementwerte in konstanten Objekten ändern. Dazu muß dem änderbaren Element das Schlüsselwort mutable vorangestellt werden und die konstante Methode muß natürlich dieses Element bearbeiten (sonst ist das ja witzlos). Desweiteren kann man die Konstantheit eines konstanten Objekts im Nachhinein weg-casten und so übergehen. Beispiel:

Quellcode:const int = 100;
const int *ptr_i = &i;
*ptr_i = 0; // Geht nicht

int *ptr_q = const_cast<int*>(&i);
*ptr_q = 0; // Jetzt funzts...

Cu

--

K:R-I)Z++
"CSS ist cascading style sheets. Und nicht so'n Ranzspiel." - dp
In memory of Voice († 2005/03/30)


Dieser Beitrag wurde am 29.08.2001 um 01:12 von Kriz bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
018
29.08.2001, 12:12
Mazze



i?
es gibt gar kein i bei dir!
ich denke mal die obere Zeile soll so heißen:
const int i = 100;

--

BattleTech-MOD:
http://bthl.unitedgaming.net/

zum Seitenanfang zum Seitenende Profil || Suche
019
29.08.2001, 20:43
Prefect



Kriz, ein Copyconstructor müßte eigentlich durchaus auch einen nicht-const-Parameter nehmen können, genauso wie ein operator=. Wir wär's mit einem =-Operator der von links nach rechts statt von rechts nach links kopiert? *g*

Und ich sage immer noch, dass das zweite const ein Typmodifizierer für den this-Pointer ist. Dass man bei einem const-Objekt keine nicht-const-Methode aufrufen kann ist natürlich klar, da dadurch der this-pointer von (const CFoo *) auf (CFoo *) gecastet werden müßte. Bzw:

Quellcode:
class CFoo {
...
int GetBar() const;
void SetBar(int bar);
};

...

const CFoo *pconst = (woher_auch_immer_das_objekt_kommt);
pconst->SetBar(100); // illegal
int i = pconst->GetBar(); // legal

CFoo *pfoo = (CFoo *)pconst;
pfoo->SetBar(55); // legal

Es kann übrigens gut sein, dass wir das gleiche meinen, es aber anders formulieren...

cu,
Prefect

--

Widelands - Gemütliche Aufbaustrategie, Free Software
Noch ein Blog - Lerne, wie die Welt wirklich ist, aber vergiss niemals, wie sie sein sollte.


Dieser Beitrag wurde am 29.08.2001 um 20:44 von Prefect bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
020
29.08.2001, 22:39
Kriz



Natürlich kann der Kopierkonstruktor ne nichtkonstante Referenz annehmen, aber dann kann man (wenn die Klasse öffentlich als Bibliothek oder so bereitgestellt wird) in seiner eigenen Implementierung im Kopierkonstruktor das Parameterobjekt verändern, was ja nicht Sinn der Sache ist (aber das muß ich dir ja nicht weiter erklären).

Desweiteren reden wir tatsächlich von ein- und demselben, nur daß du es in komplizierte Worte packst =). Auch wenn ich mir nicht da so 100%ig sicher bin in deiner Aussage, da der this-Zeiger eines konstanten Objekts durch seine Deklaration usw. mittels voranstehendem const in diese Richtung modifiziert wird. Also habe ich mal in meinen alten Akten und Büchern nachgeblättert. Und in der Tat ist es wohl eher so, wie es meine, daß das 2. const eine Art Modifizierer ist, der als Fahrschein für konstante Methodenaufrufe dient. Im Prinzip genauso ein Bezeichner wie für abstrakte Methoden:
Quellcode:class CFoo
{
public:
...
void Abstrakt(void) = 0; // Abstrakte Deklaration
};

//////

class CFoo2 : public CFoo
{
public:
...
void Abstrakt(void); // Auflösung der abstrakten Methode aus CFoo
};

Aber das kennst du ja auch, also von daher...

Ist ja auch schnurz, jedenfalls brauchts konstante Methoden, die von konstanten Objekten aufgerufen werden...

Cu

PS: Da fällt mir ein: Wieso hat es nie ein Schlüsselwort abstract gegeben in C++? Ist logischer zu schreiben
Quellcode:abstract void Abstrakt(void);
als
Quellcode:void Abstrakt(void) = 0;
Hm...

--

K:R-I)Z++
"CSS ist cascading style sheets. Und nicht so'n Ranzspiel." - dp
In memory of Voice († 2005/03/30)


Dieser Beitrag wurde am 29.08.2001 um 22:41 von Kriz bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
021
30.08.2001, 17:08
Hanky



Das frag mal die von Borland oder MS...:P

--

hankYs Page

zum Seitenanfang zum Seitenende Profil || Suche
022
30.08.2001, 17:27
Kriz



Nope, das wäre eine Frage an Bjarne Stroustrup gewesen...

--

K:R-I)Z++
"CSS ist cascading style sheets. Und nicht so'n Ranzspiel." - dp
In memory of Voice († 2005/03/30)

zum Seitenanfang zum Seitenende Profil || Suche
023
30.08.2001, 17:38
Hanky



hat der alles alleine gemacht? (c/C++)

--

hankYs Page

zum Seitenanfang zum Seitenende Profil || Suche
024
30.08.2001, 17:42
Kriz



In meinem C++-Online-Tut auf CAWS steht ganz genau, wer was wann wie wo gemacht hat =)

--

K:R-I)Z++
"CSS ist cascading style sheets. Und nicht so'n Ranzspiel." - dp
In memory of Voice († 2005/03/30)

zum Seitenanfang zum Seitenende Profil || Suche