4

I'm new to C++, I have more experience in OCaml and Python. I want to learn C++ by making a program playing "Morpion Solitaire". My beginnings are a bit difficult.

In the following code :

typedef enum {NORTH, NORTHEAST, EAST, SOUTHEAST} direction;

char deltax[4] = { 0, 1, 1, 1};
char deltay[4] = { 1, 1, 0, -1};

class Coords {
 private:
  char x,y;

 public:
  Coords(char xx,char yy){
    x = xx;
    y = yy;
  };

  char get_x() const { return x;}

  char get_y() const { return y;}
};

class Line {
 private:
  Coords orig;
  direction dir;
  Coords newcross;

 public:
  Line(char x1, char y1, direction d, char x2, char y2) {
    orig = Coords(x1,y1);
    dir = d;
    newcross = Coords(x2,y2);
  };

  Coords nthpoint(char n) {
    char x,y;

    x = orig.get_x() + n*deltax[dir];
    y = orig.get_y() + n*deltay[dir];

    return Coords(x,y);
  };
};

the compiler tells me this :

nico@gaston:~/Travail/Cplusplus/morpion++$ g++ -c morpion.cc 
morpion.cc: In constructor ‘Line::Line(char, char, direction, char, char)’:
morpion.cc:29:57: error: no matching function for call to ‘Coords::Coords()’
   Line(char x1, char y1, direction d, char x2, char y2) {
                                                         ^
morpion.cc:29:57: note: candidates are:
morpion.cc:11:3: note: Coords::Coords(char, char)
   Coords(char xx,char yy){
   ^
morpion.cc:11:3: note:   candidate expects 2 arguments, 0 provided
morpion.cc:6:7: note: Coords::Coords(const Coords&)

I don't understand the message. I have given a 2 argument constructor for class Coords, but the compiler keeps telling me that orig = Coords(x1,y1) calls the constructor with 0 arguments.

What did I miss ?

Remark : I initially put the declarations of Coords and Line in different files, and thought I did not use the proper #include, but putting everything in one single file didn't solve the problem...

quamrana
  • 37,849
  • 12
  • 53
  • 71
  • 1
    The compiler doesn't point to `orig = Coords(x1,y1)` (which is an assignment and not an initialisation, by the way) but to the space between the parameter list and the function body. [Here](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) is the list of recommended books. – molbdnilo Aug 08 '16 at 14:05
  • Prefer initializer lists to assignments in the constructor's body. Also prefer C++11 member initialization and uniform initialization. – Kuba hasn't forgotten Monica Aug 08 '16 at 14:11

3 Answers3

6
Line(char x1, char y1, direction d, char x2, char y2)
  : orig(x1,y1), dir(d), newcross(x2, y2) {}

Coords doesn't have a default constructor. Your original code attempts to first default-construct orig, then assign a new value to it. But for lack of that default constructor, the first step fails.

Igor Tandetnik
  • 50,461
  • 4
  • 56
  • 85
5

The problem you are having is that all class members and basses must be constructed before entering the constructor body. Because of that what your constructor actually looks like after having the implicit constructions added by the compiler is

Line(char x1, char y1, direction d, char x2, char y2): orig(), dir(), newcross() {
    orig = Coords(x1,y1); // this is assignment not construction
    dir = d; // this is assignment not construction
    newcross = Coords(x2,y2); // this is assignment not construction
};

This is not a problem for dir since it can be implicitly constructed but Coords is not so orig() and newcross() fails.

To fix this you need to use the member initialization list and have a constructor like

Line(char x1, char y1, direction d, char x2, char y2) : orig(x1, y1), newcross(x2, y2), dir(d) {}
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
1

TL;DR: the fix:

Line(char x1, char y1, direction d, char x2, char y2) :
    orig(x1, y1), newcross(x2, y2), dir(d)
{
};

The constructor of class Line is to call constructors of all members of this class, and does this prior to the execution of constructor body. That is, the member orig should be constructed before line

orig = Coords(x1,y1);

execution. By default, the default constructor is called, but in your case the class Coords has no default constructor. When we write orig(x1, y1), we override the default, and the constructor Coords(x1, y1) is called to construct orig.

alexeykuzmin0
  • 6,344
  • 2
  • 28
  • 51
  • Thanks for your help guys. So fast !!! :-) I saw this syntax in the C++ book from Stroustrup, didn't understand it at the moment. I'm releived :-P – Nicolas FRANCOIS Aug 08 '16 at 14:05
  • Downvoter, care to reverse after the edit? This is fine now. – underscore_d Aug 08 '16 at 14:07
  • 1
    BTW the initialization list should be in the order of declaration, else compiler will moan. That is, `orig(...), dir(...), newcross(...)`, not `orig(...), newcross(...), dir(...)`. – anatolyg Aug 08 '16 at 14:38