gängige Anfänger-Fehler?
-
Ich mein es schon wie es da steht. Viele Anfänger initialisieren ihre Variablen nicht und wundern sich später. Auch zerstören sie Objekte gern mit delete und prüfen später den Pointer auf !=NULL. Natürlich wurde der Pointer nie auf NULL gesetzt, weshalb die Anfänger m it schöne Zugriffsverletzungen belohnt werden, wenn SIe sich dann in sicherheit wiegen und munter den Pointer benutzen wollen.
-
Zwei richtig miese Anfängerfehler sind folgende:
1.)
for(int i = 0; i <= count; ++i) // autsch Bereichsüberschreitung! array[i] = 0;
2.)
for(int i = 0; i < sizeof(array); ++i) // autsch, wenn sizeof(array[0]) > 1 array[i] = 0;
Auch immer wieder beliebt sind Präprozessorfehler:
#define XYZ (var1-var2) ... int XYZ = 0;
#define MUL(a,b) a*b ... int c = MUL(a+1,b+1); // wird zu a+1*b+1 also a+b+1
-
naja, ging wohl eigentlich nur um Fehler die der Compiler meldet. Naja, ein weiterer beliebter Fehler ist
#define MAX(a,b) (a>b?a:b)
-
kingruedi schrieb:
Naja, ein weiterer beliebter Fehler ist
#define MAX(a,b) (a>b?a:b)
wobei ein Anfänger wohl keine Makros benutzt (zumindest unter C++). Er wird wohl inline beforzugen, da man es im gewohnten FunktionsDesing verwenden kann.
-
kingruedi schrieb:
naja, ging wohl eigentlich nur um Fehler die der Compiler meldet.
Exakt. Ich suche primär Fehler die der Compiler meldet - aber nicht immer ganz klar. So kommt bei einem ; nach einer class definition 'sinnlose' Fehler, die ja nur indirekt mit dem ; zu tun haben.
Genau sowas suche ich.
Aber die anderen Fehler kann man in ein Kapitel 'Pitfalls' sicher auch recht gut einpacken
Danke für eure Mühe und nur weiter so!
-
oder:
template <class T> class foo { public: foo(); }; foo::foo() { }
11 C:\Dev-Cpp\main.cpp
syntax error before `::' tokenwird auch gern genommen, genau wie die klassische Kombination von cpp-Dateien und templates. Aber das hat Shade bestimmt schon dabei...
-
Mir ist nochwas eingefallen:
const-Zeiger und Zeiger auf const:char c = 'P'; const char* pc; //Zeiger auf const char* const pc4 = &c; //constanter Zeiger const char* const pc5 = &c; //constanter Zeiger auf const
-
Hallo,
ein ganz simpler Fehler, der den VC 6 immerhin zu einem ICE bringt:class Foo { public: ~Foo(); }; Foo::~Foo {}
Ein simpler "typename fehlt"-Fehler:
template <class T> struct Foo { typedef T::Type Type; };
Und ein Fehler, der von kaum einem Compiler erkannt wird:
template <class T> struct Foo { int i; }; template <class U> struct Bar : public Foo<U> { void func() { i = 22; } };
-
@hume: kannst du das erste mal beschreiben? und was ist ein ICE?
-
ach bestimmt ein internal compiler error. aber warum? sehe den fehler nicht.
-
sehe den fehler nicht
Es fehlt die, in diesem Fall leere, Parameterliste.
// so ist's richtig Foo::~Foo() {}
-
HumeSikkins schrieb:
Und ein Fehler, der von kaum einem Compiler erkannt wird:
template <class T> struct Foo { int i; }; template <class U> struct Bar : public Foo<U> { void func() { i = 22; } };
um ehrlich zu sein, habe ich den Sinn auch nie verstanden... da i nicht in Bar enthalten ist, müsste er IMHO als nächstes in Foo<U> suchen. Was viele Compiler auch so machen. Du weisst nicht zufällig warum man hier this->i stattdessen schreiben muss?
-
Du weisst nicht zufällig warum man hier this->i stattdessen schreiben muss?
Ich wäre ein Gugelhupf, wenn ich den Ursprung eines mir bekannten Fehlers ignorieren würde
Die Antwort findest du in 14.6.2.8:
in the definition of a class template [...], if a base class of this template depends on a template parameter, the base class scope is not examined during name lookup until the class is instantiated.
Der base class scope wird also schon mal nicht berücksichtigt. Da i nun aber kein abhängiger Name ist, wird die Gültigkeit von i bereits in der ersten Phase der Templateprüfung getestet. Es gibt hier kein bekanntes i -> Fehler.
Durch die Qualifizierung mit this-> oder Foo<U>:: wird i ein abhängiger Name und erst bei der Instanziierung des Templates geprüft -> Kein Problem.
Nötig ist das Ganze um spätere explizite oder partielle Spezialisierungen der Basisklasse unterstützen zu können.
Ich habe dazu am 9.5.2002 schon mal einen ewig langen Beitrag geschrieben, dessen Wiederholung hier aber nicht lohnt
-
HumeSikkins schrieb:
Nötig ist das Ganze um spätere explizite oder partielle Spezialisierungen der Basisklasse unterstützen zu können.
Genau das interessiert mich. Den 'Grund' - weil es so im Standard steht - kannte ich. Mich interessiert es aber, WARUM es so im standard steht
Kannst du zB ein minimalbeispiel machen? Oder einen Link posten? Danke
Ich habe dazu am 9.5.2002 schon mal einen ewig langen Beitrag geschrieben, dessen Wiederholung hier aber nicht lohnt
Ähm... Ich habe gesucht, aber das einzige was ich von dir Gefunden habe war am 8.5. bezüglich eines Umzugs... Sorry
Du weisst nicht zufällig den Titel des Threads?
-
Ich habe gesucht, aber das einzige was ich von dir Gefunden habe war am 8.5. bezüglich eines Umzugs... Sorry
2002?
Du weisst nicht zufällig den Titel des Threads?
Das Thema hieß: "Compilerumfrage"
Mich interessiert es aber, WARUM es so im standard steht Kannst du zB ein minimalbeispiel machen?
So wie ich das sehe, braucht man diese Regel hauptsächlich im Zusammenhang mit der zweistufigen Templateprüfung, wie sie im Standard beschrieben steht.
Würden unabhängige Namen auch im Basisklassenscope einer von einem Templateparameter abhängigen Templatebasisklasse gesucht werden, dann würden solche Namen zu früh gebunden werden. Eine spätere Spezialisierung der Basisklasse könnte diese Bindung aber ungültig machen:// Meine Lib.h template <class T> struct Base { void foo() {} }; template <class T> struct Derived : public Base<T> { void bar() { foo(); } }; // Irgendwo in Deine Lib.h template <> struct Base<int> { }; int main() { Derived<int> d; d.bar(); }
Ein Compiler der Templates immer erst bei der Instanziierung prüft (wie z.B. der VC 6.0) kann in solch einem Fall die oben genannte Regel ignorieren. Er wird trotzdem den richtigen Code generieren, da er ja zum Zeitpunkt der Instanziierung insbesondere auch die Spezialisierung kennt.
Zu einem wirklichen Problem wird es, wenn ein Name an eine freie Funktion gebunden ist, eine spätere Spezialisierung einer Basisklasse aber eine Methode mit selben Namen einführt. Würde die genannte Regel nicht existieren, würde damit die vorherige Bindung aufgehoben werden, da der Basisklassenscope schließlich "näher dran" ist als der globale Scope.
Minimalbeispiel:
#include <cassert> // Meine Lib.h void aFunction() {} template <class T> struct Base {}; template <class T> struct Derived : public Base<T> { void foo() { aFunction(); // ::aFunction } }; // Irgendwo in Deine Lib.h template <> struct Base<int> { void aFunction() // Ups { assert(false); } }; int main() { Derived<int> d; d.foo(); }
Ein Compiler der die Regel nicht berücksichtigt wird hier die Methode aufrufen und damit das Programm beenden. Ein konformer Compiler hingegen ignoriert den Basisklassenscope und bindet den unabhängigen (unqualifizierten) Namen aFunction immer an die freie Funktion, egal was du oder ich mit dem Basisklassentemplate machen.
-
Ich wette, das der hier so ausführlich besprochene Fehler nicht nur ein Anfängerfehler ist, sondern auch Fortgeschrittene ihn nicht erkenne werden.
-
Helium schrieb:
Ich wette, das der hier so ausführlich besprochene Fehler nicht nur ein Anfängerfehler ist, sondern auch Fortgeschrittene ihn nicht erkenne werden.
Ja. Tut mir leid. Ich hatte das "Anfänger" im Threadtitel beim Posten irgendwie überlesen. Insofern ist die ganze Diskussion OT. Vergesst doch einfach meinen Beitrag und redet ganz normal weiter. Vielleicht kann kingruedi sogar noch was reparieren.
-
Ein ebenfalls netter Fehler kommt, wenn man eine } vergisst.
Dann wird gemeldet: Unerwartetes Dateiende
... oder so ähnlich.
-
char i;
for (i=0; i<256; i++)
...
-
den sehe ich oft...
string hey (); int main() { cout<<hey; } string hey(){ return "hallo hey"; }