Noen grunnleggende feil/fallgruver/feller i C/C++:

(Syntaktiske og semantiske. Ingenting om string-klassen eller STL her.)

  1. Manglende bruk av korrekt 'namespace' (mest vanlig er å glemme: 'using namespace std;').
     
  2. Glemmer å include aktuell (.h-)fil.
     
  3. Programsetning med preprosessor-direktiv avsluttes med ';':
          #include <iostream>;      //  Ingen preprosessor-direktiver
          #define  PI  3.1415926;   //    avsluttes med ';' :
          #if !defined(XXX)
             #define XXX;
          #endif;
          
  4. Høyre- og venstresiden er byttet om i en tilordning:
          a * b = svar;     // Sidene er byttet om.
          
  5. Rett rekkefølge på operatorer/tegn ved aritmetisk tilordning:
          int a = 94,  b = 312;
          a =- 4;           // Tror at 'a' minskes med 4, slik at den får verdien 90.
                            //   'a' blir satt til -4(!). Må skrive:  a -= 4;
          b =+ 18;          // Tror at 'b' økes med 18, slik at den får verdien 330.
                            //   'b' blir satt til 18(!). Må skrive:  b += 18;
          
  6. Bruk av udefinert/feilskrevet variabel:
          int ant1 = 26, ant2 = 7;
          float antSum;
          antsum = ant1 + ant2;    // 'antsum' er skrevet uten stor 'S'.
          
  7. Divisjon med bare int'er slik at desimalene bare forsvinner (avrundes ikke):
          int ant1 = 26, ant2 = 7;
          float svar;
          svar = ant1 / ant2;     // svar = 3, Regner med to 'int'-er.
                                  //   Mister bare desimalene/avrundes ikke.
          
  8. Unødvendig Warning:
          float tall = 12.8;      // Mange kompilatorer vil her kunne gi en Warning,
                                  //   f.eks. 'initialzing': truncation from 'const double' to 'float'.
                                  //   Husk derfor å ha med 'F', dvs.  float tall = 12.8F;
          
  9. Caster ikke automatisk til "lavere" type:
          char ch = 'A';
          cout << ch              // Får skrevet 'A' (ASCII-verdi er 65).
               << ch+1;           // Får skrevet 66, da regner totaluttrykket som int!
                                  //    Måtte ha skrevet:  char(ch+1)
          
  10. Divisjon med '0'.
     
  11. "Sprenger" en variabels verdiområde ved utregning:
          int a = 1000000, b = 100000, c = 1000, d;
          d = a * b / c;          //  En int kan max. være 2.147.483.647. 'a*b' blir for stort for dette.
                                  //     Dermed blir noe "søppel" dividert med 'c', og gir dermed feil svar.
                                  //     Må derfor skrive:  d = a * (b / c)   eller   d = a / c * b
          
  12. Ikke-matchende datatyper i uttrykk:
          int a;
          char b;
          float c;
          c = a / b;         //  Faktisk lovlig, men virker kanskje noe merkelig.
    
             eller
    
          char a[] = "TEKST";
          char * p = a;
          if (p == 'T')      // 'p' er en peker og ikke en char-variabel. Må evt. bruke '*p'.
             cout << ".......";
          
  13. Initialiserer ikke variable (inneholder istedet tilfeldig "søppel"):
          int sum, tall;
          do  {
            cout << "Skriv et tall: ";  cin >> tall;
            sum += tall;            //  'sum' er ikke nullstilt, derfor adderes 
          } while (tall != 0);      //     'tall' til tilfeldig "søppel".
          
  14. Manglende gåsøyne til slutt i tekststreng:
          cout << "Denne teksten blir skrevet ut;     
               eller
          char tekst[] = "Dette er en test-tekst;     // Begge mangler avsluttende '"';
                 //  Fort gjort å også glemme:   , (komma)   ' (apostrof)   \ (backslash)
          
  15. Ikke-matchende antall parenteser:
          if ((a = sqrt(b)) != ((6+ant)*(100-ant2))     // Mangler en ')' helt til slutt.
          
  16. Inkrement av samme variabel to ganger i samme uttrykk:
          a = i++ * i++;        //  Uklart om ++ skjer mellom utregningen eller to ganger først til slutt.
          
  17. Misforstått operator-presedens:
          svar = a - b * c + d;    //  Vil beregnes som:   (a - (b * c)) + d
          
  18. Feil bruk av sammenligningsoperatorer:
    • Tegnene '>' og '<' er snudd feil vei (logisk/semantisk).
    • Byttet rekkefølgen til   '<'   og   '='   i   '<='   (syntaktisk).
    • Byttet rekkefølgen til   '>'   og   '='   i   '>='   (syntaktisk).
    • Byttet rekkefølgen til   '!'   og   '='   i   '!='   til   '=!'   (logisk/semantisk).
      Dette medfører at det på venstre side settes til (får verdien av) NOT ('!') til det på høyre side!
    eller
          if ( -0.5 <= x <= 0.5 ) ....  // Sammenligner  -0.5 <= x  (svaret er 0 eller 1)
                                        //   sammenligner så dette svaret med 0.5.
                                        // Burde ha skrevet: 
                                        //   if ( -0.5 <= x  &&  x <= 0.5 ) ....
            
          
  19. Bruker '=' istedet for '==' når skal sammenligne uttrykk:
          if (a = 5)                    // 'a' blir satt lik 5, som alltid er mulig/sant/true.
             cout << "A er lik 5";      //    Skulle i stedet ha brukt '==' (for å sammenligne).
          else
             cout << "A er ulik 5";
          
  20. '&&' betyr 'AND', '||' betyr 'OR',   men bare en '&' eller '|' betyr noe helt annet ......
     
  21. Feil bruk av parenteser:
          if (a = hentTall() != 0)      //  'a' blir alltid 0 eller 1. Det 'hentTall()' returnerer 
            .......                     //   sammenlignes med 0. Svaret (true (1) eller false (0)) 
                                        //   legges inn i 'a'.  Må skrive: ((a = hentTall()) != 0).
                                        //   Dermed blir 'a' tilordnet det funksjonens returverdi,
                                        //   før 'a' sammenlignes med 0.
          
  22. Løkke har intet innhold/kropp, da har brukt ';' rett etter løkketesten:
          for (int i = 0;  i <= 5;  i++);     // Løkka er tom, da ';' er brukt til slutt på linja.
              cout << a[i];
          
  23. Manglende '{' og '}' rundt (en-linjes) funksjonskropp eller sammensatt uttrykk/setninger:
          char ch;
          cin >> ch;                           // Om innlest 'ch' er ulik 'n' vil 
          while (ch != 'n')                    //   løkka gå uendelig da innmaten
             cout << ch << ' ' << ch << '\n';  //   bare er EN utskriftslinje (har glemt 
             cin >> ch;                        //   omsluttende krøllparenteser).
          
  24. Uendelige løkker (pga. logisk feil i testuttrykket eller at det ikke endrer seg):
          char svar;
          do  {
            .......
            cout << "Fortsette (j/n)?  ";  cin >> svar;
          } while (svar != 'n'  ||  svar != 'N');     // 'svar' vil alltid være ulik
                                                      //   ENTEN 'n' ELLER 'N'.
          
  25. Går en for langt/kort i løkke:
          int tall;
          cout << "Skriv inn 7 tall:  ";
          for (int i = 1;  i < 7;  i++)     // Løkka går bare 6 ganger.
              cin >> tall;
          
  26. Ikke-matchende antall '{' og '}'.
     
  27. Glemmer ";" etter en-linjes if-setning:
          if (a == 5)                   
             cout << "A er lik 5"       //    Glemt ";" til slutt på setningen.
          else
             cout << "A er ulik 5";
          
  28. 'else if' brukt aller først i et testuttrykk:
          else if (a >= 10)              // Ikke 'else' aller først i 'if'-uttrykk.
            cout << "A er større enn eller lik 10";
          else if (a <= 0)
            cout << "A er mindre enn eller lik 0";
          else
            cout << "A er større enn 0 men mindre enn 10";
          
  29. Dinglende else (pga. manglende bruk av '{' og '}' blir ikke rett 'if' og 'else' matchende hverandre):
          if (a >= 0)
             if (a > 100)
                cout << "A er større enn 100";
          else                              //  'else' blir tilhørende den SISTE 'if'-setningen,
             cout << "A er mindre enn 0";   //     selv om det visuelt ser anderledes ut.
          
  30. Bytter om bruken av 'while' og 'if':
          int tall;
          cout << "Skriv tall: ";  cin >> tall;
          if (tall <= 0  ||  tall > 100)  {     // Må bruke 'while', da ønsker egentlig å være
            cout << "Skriv tall (1-100): ";     //   garantert at 'tall' blir mellom 1 og 100.
            cin >> tall;                        //   Her testet det bare EN gang.
          }                                     
          
  31. Manglende 'break;' i 'switch/case'-setninger:
          switch (tall)  {
           case 1: cout << "1";                 // Om 'tall' har verdien 1, vil utskriften "1234" komme.
           case 2: cout << "2";                 //   Dette skyldes at om en 'case' er sann/true, så vil 
           case 3: cout << "3";                 //   all etterfølgende kode utføres frem til den første 'break'.
           case 4: cout << "4";                 //   Derfor  hver 'case'-setning avsluttes med en 'break;'.
          }
          
  32. Initierer arrayer eller (nestede) struct'er feil:
          int a[5] = { '1', '2', '3', '4', '5' };   //  int-array, ikke char-array.
             eller
          int b[5] = { 1, 2, 3, 4, 5, 6 };          //  Legger inn et tall for mye ift.lengden.
             eller
          char c[] = 'TEST-TEKST';                  //  Tekster omsluttes av " (gåsøyne).
    
             eller
    
          struct A {
            int b;  float c;
          };
          struct D  {
            A  a1, a2;
          }
          int main()  {
            D dd =  { { 1, 1.1F }, { 2, 2.2 F } };  //  Korrekt initiering!
            .......
          }
          
  33. Håndtering av hele struct'er og deres datamedlemmer:
          struct A {
            int b;  float c;
          };
          A a1, a2 = { 7, 4.8F };
                                  //  Kan ikke håndtere hele struct'en som en helhet ved utskrift
          cout << a2;             //    og innlesing.  behandle datamedlemmene/feltene enkeltvis.
          cin >> a1;              //    Altså:  cout << a2.b << ' ' << a2.c;  og  cin >> a1.b >> a1.c;
          a1 = a2;                //  Men, dette er lovlig - kopiere hele struct'er!
          
  34. Manglende ';' etter enkle uttrykk, funksjons-, struct- eller klasse-deklarasjoner:
          int a(int b, int c)     // Deklarasjon av/heading for funksjon. Glemt ';'.
    
              eller
    
          struct D  {       class H  {
            int e;            ........
            float f;          ........
            char g;           ........
          }                 }     // Glemt ';' etter avsluttende '}' begge steder.
          
  35. Kaller funksjon uten tom "()":
          void a()  {
            .......
          }
          int main()  {
            .......
            a;                    //  Glemt tom "()". Funksjonen kalles/kjøres ikke !
            .......
          }
          
  36. 'void'-funksjon som returnerer verdi:
          void a(int b, int c)  {
            int d = b * c;
            return d;         //  Returnerer verdi, selv om headingen sier noe annet.
          }
          
  37. Manglende 'return' i funksjon som skal returnere en verdi:
          int regnUt(int a, int b)  {
              int c = a * b;     //  Retunerer ikke svaret ('c').
          }
          
  38. Verdioverføring istedet for referanseoverføring når funksjonsparametre trenger å modifiseres:
          void (int a, int b)  {
            cin >> a;     // Kun de lokale (formelle) variablene 'a' og 'b' oppdateres,
            cin >> b;     //   og ikke de medsendte (aktuelle). Dette skyldes at '&'
          }               //   er utelatt/glemt etter begge 'int'-ene.
          
  39. Bruk av mange globale variable (ikke feil, men dårlig programmering).
     
  40. Ikke-synlig/-tilgjengelig variabel:
          void funk()  {
            .......
            cout << ant;       //  "ant" er ikke tilgjengelig (usynlig),
          }                    //     da er definert inni "main".
          int main()  {
            int ant;
            .......
          }
          
  41. Forvirrende bruk av (like) variabelnavn (lokale vs. globale, formelle vs. aktuelle):
          int a, b;
          int regnUt(int a, int b)  {    // Lokale 'a' og 'b' er andre variable enn de globale,
              return(++a * ++b);         //    selv om de verdioverføres og dermed initielt  
          }                              //    får de samme verdiene som de globale 'a' og 'b'.
          .......                 
          regnut(a, b);     
          
  42. Bruker noe (variabel, struct, funksjon, klasse) før den er deklarert/definert:
          void funk()  {
            cout << nr;       //  Bruker "nr" før den er definert.
          }
    
          int nr;
    
          int main()  {
            .......
          }
    
             eller
    
          class A  {
            .......
            B bobj;           //  Lager et B-objekt, før "B" er deklarert.
          };
          class B  {
            .......
          };
          
  43. Default-/standard-argumenter angis både ved deklarasjon og definisjon:
          void funk(int a = 7, char ch = 'X');
    
          int main() {
             ........
          }
    
          void funk(int a = 7, char ch = 'X')  {  //  Default-argument er angitt tidligere, 
             ........                             //    og skal ikke spesifiseres også her.
          }                                       //    Altså bare: void funk(int a, char ch)
          
  44. Prøver å aksessere noe som er private/protected:
          class A  {
            private:
              int a;
            public:
              void b()  { ....... }
          };
    
          int main()  {
            A aa;
            aa.b();
            aa.a = 17;       //  Ulovlig, da "a" er private/skjult/hidden.
            .......
          }
          
  45. Glemmer å angi private data/funksjoner som 'private':
          class A  {
                             //  Utelatt/glemt 'private'. Egentlig helt greit, da blir ellers automatisk også 'private'.
              int a;         //  Men en god sedvane å også angi det som 'private' som skal være det.
            public:
              ......
              ......
          };
          
  46. Prøver å initiere datamedlemmer ved klasse-deklarasjon:
          class A  {
            private:
              int  a  =  0;   //  Dessverre ikke lovlig/mulig å initiere dataene under
              char ch = 'X';  //    selve deklarasjonen. Dette må constructoren(e) gjøre.
            public:
              ........
          };
          
  47. Tror at lager nytt objekt når opprettes vha. tomme parenteser:
          class A  {
            .......
            public:
              A()  { ....... }
          };
    
          int main()  {
            A a1;                 //  OK - objektet 'a1' opprettes/lages.
            A a2();               //  Intet nytt objekt opprettes/lages.
            .......               //    Dette er deklarasjonen/prototypen for den parameterløse
          }                       //    funksjonen 'a2' som returnerer et A-objekt!
          
  48. Ombytting av ":" og "::":
          class A {
            .......
          };
          class B : public A  {    //  Ved arv brukes EN ":"
            .......
            void funk();
          };
          void B :: funk()  {      //  Ved klasse-tilhørighet brukes TO "::"
            .......
          }
          
  49. Glemmer "::" ved definisjon av medlemsfunksjon utenfor klassen:
          class A  {
            .......
            public:
              void funk();      //  Deklarerer medlemsfunksjon (kun heading).
          };
    
          funk()  {             //  Skal definere medlemsfunksjonens innmat/kode,
            .......             //    men skriver ikke "A::funk()". Derfor blir dette
          }                     //    en annen, likenavnet og "global" funksjon.
          
  50. +/-1 feil ved array-indeksering:
          int a[5] = { 1, 2, 4, 8, 16 };     // Arrayen har indeksene 0-4.
          for (int i = 0;  i <= 5;  i++)     // Løkka går EN for langt.
              cout << a[i];
          
  51. Array som parameter håndtert feil:
          int a[10];
          void funk(int b[10]);
            .......
          funk(a[10]) ;     // Skal bare sende med 'a' og ikke "skuff"
                            //    nr.10 (a[10]) (som faktisk ikke finnes).
          
  52. Mister/glemmer '\0' ved (manuell) strenghåndtering:
          char a[] = "TEST-TEKST";
          char b[10];
          strncpy(b, a, 4);   //  '\0' blir ikke tillagt på slutten,
          b[4] = '\0';        //     må gjøre dette manuelt.
          
  53. Mister tekst ved blandet innlesing vha. >> og getline(...):
          int a;
          char b[20], c[20];
          cin >> a;            //  >> blar seg forbi/ignorerer blanke (space), tab og linjeskift ('\n').
          cin >> b;            //    Derfor leses det første ikke-blanke inn i 'a' og 'b'.
                               //  Her vil 'c' kun bli fylt med en totalt tom tekst, dvs. c[0] = '\0'!
          cin.getline(c, 20);  //    Dette skyldes at det bare ligger igjen en '\n' i inn-bufferen fra
                               //    den forrige innlesingen. Derfor må man, når man slik veksler mellom
                               //    lesing vha. >>  og getline, avslutte forrige >> innlesing med cin.ignore();
                               //    Dermed forkastet den igjenliggende '\n', og neste getline starter med
                               //    totalt tomt input-buffer.
                               //    NB: getline leser t.o.m.'\n', men denne blir ikke en del av input-teksten.
          
  54. Kaller seg selv (rekursjon), istedet for likenavnet funksjon i base-klasse:
          class A {
            ......
            public:
              void display()  { ..... }
          };
    
          class B :: public A  {
            ......
            public:                                         //  Kaller her seg selv uendelig.
              void display()  { .....  display();  ..... }  //  Må skrive:  A::display();
          };
          
  55. Overskrivende funksjoner (ved arv) skjuler også overloadede funksjoner:
          class A {
            ......
            public:
              void funk(float n)  { ..... }
              void funk(int   n)  { ..... }
          };
          class B : public A  { 
            ......
            public:
              void funk(float n)  { ..... }
          };
    
          int main()  {
           B b1;
           b1.funk(3);        //  'funk' i B kjøres. Så lenge de overloadede er overskrevet, så tilkalles
           ......             //      den nærmeste (i B) - for maskinen vet hvordan konvertere int til float.
          }
          
  56. Peker og/eller vanlig variabel:
          char * ch1, ch2;    //  'ch1' er char-peker, 'ch2' er vanlig char. Må skrive:  char * ch1, * ch2;
          
  57. Peker-aritmetikk kun aktuelt ifm. arrayer:
          char  ch = 'A';           
          char* chp = &ch;
          chp++;  chp--;      //  Peker-aritmetikk på en peker som ikke peker
                              //    til en array er meningsløst/logisk feil.
          
  58. Meningsløs peker-sammenligning/-subtraksjon:
          char t1[] = "Dette er en tekst", t2[] = "mens dette er en annen tekst";
          char * tp1, *tp2;
          tp1 = t1+4;  tp2 = t2+7;   //  Begge peker noe ut i hver sin tekst.
          if (tp1 < tp2)   ......    //  Meningsløst å sammenligne eller se på forskjellen mellom 
          if (tp2-tp1 > 2) ......    //    to pekere som refererer til hver sine (ulike) arrayer.
          
  59. Pekere ikke satt korrekt eller overskriver noe ved en feil:
          char t[] = "TESTING TESTING";
          char * p;
          strcpy (p, "TEKST");     // 'p' inneholder tilfeldig adresse og denne overskrives.
    
                eller
    
          p = t + 20;              // 'p' peker utenfor/etter teksten.
          cout << *p;
    
                eller
    
          p = new char[6];  strcpy(p, "TEKST");
          delete [] p;
          cout << p;               //  Memory er egentlig frigitt, så ikke aksesser den.
          
  60. Glemmer å sette av plass også til '\0':
          char  t[] = "Dette er en tekst";
          char* t2  = new char[strlen(t)];   //  Må huske 'strlen(t)+1', ellers blir det ikke 
          strcpy(t2, t);                     //    avsatt plass også til '\0' ved kopiering.
               eller
          char* t3  = new char[strlen(t+1)]; //  Det skal være 'strlen(t)+1' (og ikke 'strlen(t+1)'),
          strcpy(t3, t);                     //    da blir det avsatt plass til 2-to tegn  for lite!
          
  61. Forsøker å ta verdien til nullptr/NULL:
          char * ch = nullptr;
          cout << *ch;             //  Å ta verdien til nullptr/NULL, medfører Fatal Error under run-time.
          
  62. Peker oppdaterer noe som også pekes til av andre:
          char * p, * q = "xyz";
          p = q;
          *(p+1) = 'X';
          cout << q;               //    Utskriften blir "xXz", da 'q' (fortsatt) peker til den
                                   //    samme adressen (de samme verdiene) som 'p' peker til.
                                   //    Kan altså få rare bieffekter når flere peker til det samme.
          
  63. Sammenblanding ved øking av pekers verdi og innhold:
          char t[] = "Dette er en tekst";
          char * ch = t;           //  Initieres til å peke på tekstens start (bokstaven 'D').
          cout << (*ch)++;         //  verdien der 'ch' peker økes med en, altså t[0] blir 'E'.
          cout << *(ch++);         //  'E' skrives ut, og pekerens innhold økes med en (til t[1] / 'e').
          cout << *ch++;           //  = *(ch++) rett ovenfor, dvs. 'e' skrives, pekeren økes til t[2].
          
  64. Glemmer "[]" nå sletter tilpekt array:
          char* p = new char[10]; 
            .......
          delete p;                //  Glemt "[]" ifm. slettingen/frigivelsen.
          
  65. Sier "delete" om fast array/objekt o.l:
          int a[5];
          int* p = a; 
          delete [] p;             //  Peker på fast array, kan ikke slette den.
          
  66. Memory-lekkasje: Glemmer å si 'delete' (i destructor) om saker objektet/funksjoner har sagt 'new' om mens det eksisterte/levde.
     
  67. new og delete kan ikke kombineres med (C sin) malloc og free.
     
  68. Rot med peker-verdi og kommentar:
          int res, a = 3;
          int* b;
          *b = 7;
          res = a /*b;            //  '/*' er starten på en lengre kommentar. Må skrive:  res = a / *b;
    
          
  69. Bytter om bruken av "." og "->":
          class A  {
            .......
            void aa()  { ........ }
          };
          int main() {
            A  ao;
            A* ap;
            ao->aa();              //  "ao" er objekt, derfor skal "." brukes.
            ap.aa();               //  "ap" er peker, derfor skal "->" brukes.
            .......
          }
          
  70. Feil bruk av "*" og "&" ifm. pekere:
                        
          char c[6] = "TEKST";     //  Bruken av "*" og "&" er her korrekt:  
          char* p = c;             //  Lager char-peker, som initieres til starten på "c".
          cout << &p;              //  Skriver ut adressen til der "p" peker (innholdet).
          cout << *p;              //  Skriver ut char'en der "p" peker (som er 'T') (verdien).
          
  71. Tekster sammenlignes på feil måte:
           char* str = new char[10];
           strcpy(str, "AAA");
                                   //  Dette er helt greit true om adressen til 'str' er lavere enn
           if (str < "BBB")        //    adressen for den midlertidige teksten "BBB" i memory!
              ........             //    Derfor  man huske å bruke strcmp(...) ved sammenligning av tekster.
          
  72. Tror at deler med en pekers verdi, men blir starten på en kommentar (/*..... */):
           int  a,  b = 3,  c = 5;
           int* d = &c;
           a = b/*d;               //  Tror at deler 'b' med verdien av der 'd' peker.
                                   //    Men '/*' er starten på en lengre kommentar som slutter ved første '*/'.
                                   //    Må istedet skrive:  a = b / *d   eller   a = b /(*d)
          
  73. Returnerer peker til lokal variabel:
           char* funk()  {
             char tekst[20];            //  'tekst' er en lokal variabel/array, og fylles med verdi/tekst.
             cin.getline(tekst, 20);    //  Returnerer man en peker til dette, så returneres en peker til et   
             return tekst;              //    uklart definert og midlertidig minneområde (stacken). Derfor  
           }                            //    man i slike situasjoner allokere nytt og permanent minneområde (heapen)
                                        //    vha.'new', kopiere aktuell tekst dit, og så si 'return' om dette.
          
  74. Husker ikke å sette det siste elementet i listen sin neste-peker til nullptr/NULL.
     
  75. Traverserer forbi en listeslutt og/eller avleser nullptr->.....:
          Person* p = head;       
          while (p->neste->id != 99)  p = p->neste;   //  "id" er kanskje aldri "99" 
                                                      //     eller p->neste == nullptr
          
  76. Glemmer å angi hva slags måte det skal arves på:
          class A {
            ......
          };
          class B : A  {       //  Utelatt/glemt 'public', arver da automatisk på en 'private' måte.
            ......
          };
          
  77. Peker til base-klasse kan ikke peke til array med avledede objekter:
          class A {
            ......
          };
          class B : public A  { 
            ......
          };
    
          int main()  {
            A* a1;            //  Pekere til base-klasse.
            B barr[5];        //  Array med avledede objekter.
       
            a1 = new B;       //  OK at peker til avledet objekt, men får kun tak i det i 'A' og det som er virtuelt.
         
            a1 = barr;
            a1++;             //  Blir feil, da 'B'-objekt er større (og tar mer plass) enn 'A'-objekt.
            .......
          }
          
  78. Destructor i avledet klasse kalles/kjøres ikke:
          class A  {
                                                      //  Private-området er her uinteressant.
              public:
                                                      //  Constructor og andre funksjoner uinteressante.
                ~A()   { ........ }                   //  Destructor som gjør ett eller annet.
          };
    
          class B : public A  {
              public:
                ~B()   { ........ }
          };
    
          int main()  {
            A* bpek = new B;
            .........
            delete bpek;                              //  Kun A's destructor kjøres.
            .......                                   //  For å få kjørt B sin også må destructoren være virtual.
          }
          
  79. Virtuell funksjon kalles ikke fra constructor i base-klasse:
                        
          class A  {
             public:
                A()   { funkA(); }
                virtual funkA() { cout << '1'; }
          };
    
          class B : public A  {
              public:
                virtual funkA() { cout << '2'; }
          };
    
          int main()  {
            B bobj;           //  Utskriften blir '1'. Base-klassens constructor kjøres før den
          }                   //  avlededes constructor. Mao. når A's constructor kjøres finnes det
                              //  ennå ikke noe B-objekt, og dens virtueller er umulig å kalle/kjøre.
          
  80. Må selv lage overloaded '='-funksjon eller copy-constructor:
          class A  {
            private:
              char* nvn;
            .......           //  Innmat, men ingen konstruksjon av overloaded '='
          };                  //     eller copy-constructor.
    
          int main()  {
            A a1, a2;
            .......           //  a1.nvn settes til å peke på noe (vha. new).
            a2   = a1;        //  Innebygd '='-funksjon eller copy-constructor kalles, der
            A a3 = a1;        //    a2.nvn og a3.nvn blir satt til å peke på det samme som a1.nvn-peker.
            .......           //    Antagelig ikke det vi ønsket, derfor må egne funksjoner lages
          }                   //    som selv sier 'new' og kopierer innholdet reelt over.
          
  81. Copy-constructor innholder ikke referanse-overføring (&):
          class A  {
            public:
              A()     { ........ }
              A(A a)  { ........ }   // MÅ ha:  "A(A & a)", ellers vil det i det uendelig forsøkes
              .........              //   å lage nye objekter vha. copy-constructoren!
          };
    
          int main()  {
            A a1;                    //  Parameterløs constructor kjøres.
            A a2(a1);                //  Copy-constructor kalles/kjøres.
          }
          
  82. Tror at man leser fra en fil, når man egentlig ikke har funnet/åpnet den:
          ifstream innfil("FILEN-MIN.DTA");
          if (innfil)  {             //  Viktig sjekk på at filen lot seg finne/åpne.
             ........
             ........
          } else
            cout << "Finner ikke filen 'FILEN-MIN.DTA'.";
          
  83. Feil i filnavn-path:
          ifstream innfil("c:\rot\temp\noter.dta");   // Tolkes som "c:<return>ot<tab>emp<newline>oter.dta".
                                                      // Må derfor alltid bruke '\\' i filpather. 
          
  84. Feil ved filinnlesing, når dette skjer ved en kombinasjon av '>>', ignore(), get(...) og getline(...).
     

Kilder:
    - Practical Debugging in C++, Ann R.Ford and Toby J.Teorey, Prentice Hall/Pearson Education
    - How not to program in C++, Steve Oualline, No Starch Press
    - C++ How to Program - Edition N, Deitel & Deitel, Prentice Hall
    - Ulike (kortere) artikler/paper fra Internet.
    - Hjernen/fantasien til Frode Haug

 
Web-sted med andre/flere (mer avanserte) fallgruver:

Tilbake til hjemmesiden for emnet.