[C++]Compile error met G++

Pagina: 1
Acties:

  • CRiMiNaL
  • Registratie: Mei 2002
  • Laatst online: 10-01-2024
Ik ben een programma aan het schrijven op ubuntu in c++,
maar nu kwam ik gisteren een compiler error tijdens het compilen met g++ tegen waar ik echt geen snars van begrijp. Ik heb het zelfs terug gebracht naar skeleton code, maar de error blijft en ik begrijp echt niet wat er mis gaat.

Relevante code:
C++: Grid.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#ifndef GRID_H
#define GRID_H

class Grid
{
    int ** level;
    int gridWidth;
    int gridHeight;

    public:
      Grid(int grid_width, int grid_height);
      ~Grid(void);
      void createGrid(void);
      void drawGrid(void);
};
#endif


C++: Grid.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>
#include "Grid.h"

using namespace std;

Grid::Grid(int width, int height) {
  gridWidth = width;
  gridHeight = height;
  level = new int * [gridHeight];
  for(int i = 0; i < gridHeight; i++) {
    level[i] = new int[gridWidth];
  }
}

Grid::~Grid() {
  for(int i = 0; i < gridHeight; i++) {
    delete level[i];
  }
  delete [] level;
}

void Grid::createGrid() {
  for(int j = 0; j < gridHeight; j++) {
    for(int i = 0; i < gridWidth; i++) {
      if(i == 0 || j == 0 || i == (gridWidth - 1) || j == (gridHeight - 1)) {
        level[j][i] = 1;
      }
      else {
        level[j][i] = 0;
      }
    }
  }
}

void Grid::drawGrid() {
  for(int i = 0; i < gridHeight; i++) {
    for(int j = 0; j < gridWidth; j++) {
      if(level[i][j] == 1) {
        cout << "#" ;
      }
      else {
        cout << " ";
      }
    }
    cout << "\n";
  }
}


C++: AI.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#ifndef AI_H
#define AI_H

#include "Vector.h"
#include "Grid.h"

class basicAI {
  public :
    basicAI(void);

    void setEnv(Grid l);
    void findRoute(Vector v);
  protected :
    Grid env;
};
#endif


C++: AI.cpp
1
2
3
4
5
6
7
8
9
#include "AI.h"

basicAI::basicAI(void) {
 // stuff
}

void basicAI::setEnv(Grid lev) {
  env = lev;
}


C++: main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>
#include <iostream>

//#include "Vector.h"
#include "Grid.h"
#include "AI.h"

using namespace std;

int main() {
  Grid * level;
  basicAI * bot;

  level = new Grid(50,10);
  level->createGrid();
  level->drawGrid();

  bot = new basicAI();
  //bot = setEnv(level);

  cout << "Done" << endl;
  delete level;
  delete bot;
  return 0;
}

Als ik al het bovenstaande compile met:
code:
1
g++ *.cpp

krijg ik de volgende error:
code:
1
2
3
4
AI.cpp: In constructor 'basicAI::basicAI()':
AI.cpp:3: error: no matching function for call to 'Grid::Grid()'
Grid.h:11: note: candidates are: Grid::Grid(int, int)
Grid.h:5: note:                 Grid::Grid(const Grid&)

Ik snap niet waarom hij de constructor van Grid aan wil roepen in de constructor van de AI class, ik heb op google al gezocht naar deze melding, maar dit heeft mij niet dichter bij een oplossing gebracht, dus probeer ik het hier.

... MMORPG Addict.


  • BHR
  • Registratie: Februari 2002
  • Laatst online: 20:21

BHR

Is deze regel niet gewoon onderdeel van de (impliciete) constructor (zonder params):

code:
1
2
protected :
    Grid env;


Tenminste, zo werkt dat in Java wel, ik heb al een tijdje geen c++ meer gedaan :)
Nu zit ik zelf op glat ijs, maar moet je deze member niet definieren als pointer en vervolgens setEnv definieren als Grid&

[ Voor 21% gewijzigd door BHR op 17-06-2008 09:02 ]

No amount of key presses will shut off the Random Bug Generator


  • CRiMiNaL
  • Registratie: Mei 2002
  • Laatst online: 10-01-2024
Oh boy wat een domme fout zeg, dat moet inderdaad een pointer zijn.
Zat gewoon helemaal op de verkeerde plaats te zoeken, bedankt!

... MMORPG Addict.


  • Peter_B
  • Registratie: Maart 2001
  • Laatst online: 20:55
Omdat je als protected class member gebruikt van de class Grid.
De class Grid heeft geen default constructor die door basicAI kaan worden aan geroepen, Grid heeft alleen "Grid(int grid_width, int grid_height); ".
Je kan twee dingen doen:
- Of een constructor zonder argumenten,
- Of default waarde invullen in je constructor declaratie.

Discoveries are made by not following instructions.


  • schoene
  • Registratie: Maart 2003
  • Laatst online: 21:09
Letop, want in je destructor van Grid schuilt nog een fout:
Als je alloceert met new[], moet je je geheugen ook vrijgeven met delete[]. Dat doe je op je eerste niveau van je 2dimensionale array, maar niet op je tweeede.

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Sowieso is die code niet 100% netjes. In het geval dat een van die new's in de ctor loop een exception throwed, dan draait de dtor niet (want het object is niet fully constructed) en leak je geheugen.

(simpele oplossing:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ctor:
int* data;
data = new int[height*width];

public member:
int get(size_t x, size_t y) {
   if (x >= width || y >= height) {
      // error, throw, exit ... return 0
   }
 
    return data[y*width+x];
 }

dtor:
delete[] data;

of iets als:
typedef std::vector<std::vector<int> > grid_t;
danwel:
tr1::shared_ptr
)

[ Voor 49% gewijzigd door Zoijar op 17-06-2008 12:12 ]


  • CRiMiNaL
  • Registratie: Mei 2002
  • Laatst online: 10-01-2024
@ Zoijar

Bedankt voor deze les, nooit bij stil gestaan dat het allocaten van een stukje geheugen fout kan gaan en dat er dan een memleak ontstaat, nu kan ik mijn coding methoden daarop aanpassen.

... MMORPG Addict.


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Je moet eigenlijk zorgen dat een ctor altijd maar 1 enkel ding alloceert, en dat alles gealloceerd wordt in ctors. Deallocatie doe je dan in de dtors. Als de allocatie faalt, dan is het object niet volledig constructed, en wordt er dus ook geen deallocatie gedaan (wat dan ook bijna nooit moet bij een allocatie fout). Als je toch twee of meer dingen moet alloceren, dan kan je ze het beste appart encapsuleren in enkele objecten. Alle deel-objecten die namelijk volledig constructed zijn worden wel dtors voor aangeroepen.

Een smart pointer encapsuleert dus eigenlijk een stukje geheugen in een object. Als de allocatie goed gaat, dan wordt het geheugen ook gegearandeerd weer vrij gegeven door de dtor van de smart pointer, ookal faalt de ctor van jouw eigen object ergens halverwege. Maar het hoeft niet alleen om geheugen te gaan, het kan ook bv een netwerk socket zijn, of een usb poort oid. Eigenlijk moet je dus elke resource (geheugen, socket, poort, etc.) wrappen in een enkel object. De ctor doet dan allocatie/initialisatie, en de dtor doet deallocatie. Dan gaat het altijd goed, en het is veel makkelijker programmeren. Je hoeft dan in andere objecten ook vaak helemaal geen dtor meer te schrijven. Dit principe heet RAII: resource-acquisition-is-initialization, en is naar mijn idee een van de meest nuttige C++ design patterns.
Pagina: 1