0

I'm trying to compile class A, which has a member of class B, where class B has no default constructor and its only constructor requires multiple arguments. Simple, right? Apparently not...

Class A:

class SessionMediator
{
 public:
  SessionMediator()
      : map_(16,100,100)
  {}

  Tilemap map_, background_, foreground_;
};

Class B:

struct Tile2D;

class Tilemap
{
 public:
  Tilemap(const unsigned int tile_size, const unsigned int width, 
          const unsigned int height)
      : tiles_(NULL), tile_size_(tile_size)
  {
    Resize(width, height);
  }

  inline void Resize(const unsigned int width, const unsigned int height)
  { /* Allocate tiles & assign to width_, height_... */ }

  unsigned int tile_size_, width_, height_;
  Tile2D* tiles_;
};

I am instantiating SessionMediator like so:

int main(int argc, char** argv)
{
  SessionMediator session;
  return 0;
}

This is the error I am getting. I'm compiling in XCode on Mac OS 10.5.8 and the compiler is g++:

session_mediator.h: In constructor 'SessionMediator::SessionMediator()':
session_mediator.h:19: error: no matching function for call to 'Tilemap::Tilemap()'
tilemap.h:31: note: candidates are: Tilemap::Tilemap(unsigned int, unsigned int, unsigned int)
tilemap.h:26: note:                 Tilemap::Tilemap(const Tilemap&)
session_mediator.h:19: error: no matching function for call to 'Tilemap::Tilemap()'
tilemap.h:31: note: candidates are: Tilemap::Tilemap(unsigned int, unsigned int, unsigned int)
tilemap.h:26: note:                 Tilemap::Tilemap(const Tilemap&)

(Duplicate of above here)
Build failed (2 errors)

I wrote a short compilable example doing basically the same thing, to try to figure out what exactly I was doing wrong, which compiles just fine with no errors in g++:

class A
{
 public:
  A(int x, int y, int z)
      : x_(x), y_(y), z_(z)
  {}  

  int x_, y_, z_; 
};

class B
{
 public:
  B() 
    : m_a(1,2,3)
  {}  

  A m_a;
};

int main(int argc, char **argv)
{
  B test;
  return 0;
}

Why does it fail in the first example? The 3 arg constructor for Tilemap (in Ex#1) is being called in the same way that the 3 arg constructor for A is being called (in Ex#2).

The code seems pretty much identical to me in the two examples.

TPXL
  • 327
  • 1
  • 3
  • 12
  • 1
    Is there any other constructors that you have? Is line 19 that particular constructor? – vmpstr Oct 23 '12 at 19:36
  • There is another SO post similar to this: Declaring a member variable that takes a constructor parameter http://stackoverflow.com/a/7395203/391693 – farfareast Oct 23 '12 at 19:36
  • Those are the only constructors. I'll look at the other post, I tried hard to find an answer to this question before I posted but most of what I got were basic stuff about how the constructor initialization list works. – TPXL Oct 23 '12 at 19:40
  • also u r not showing how u r calling `SessionMediator` or `TileMap` like u have shown in `main` method of the example – Anirudha Oct 23 '12 at 19:47
  • Adding a section showing how SessionMediator is being instantiated. It is using the default constructor. – TPXL Oct 23 '12 at 19:53
  • @Fake.It.Til.U.Make.It: Days of favoring inheritance over containment are long gone :-). – farfareast Oct 23 '12 at 20:01
  • Try to put `map_(16u,100u,100u)` in the SessionMediator constructor call to make the constants unsigned. This is the only thing that comes to mind now :-). – farfareast Oct 23 '12 at 20:50
  • 1
    There's too much guessing going on here. You have left out some critical piece of information; edit your problem code so that it can be copy/pasted and compiled to produce the error you're running into. As currently posted (after minor fixes, such as forward declaring `Tile2D` and fixing the comment that hides a closing brace), the code code does not produce the error you're asking about with GCC/G++ or MSVC. – Michael Burr Oct 23 '12 at 22:26

4 Answers4

1

As I was trying to simplify my example a bit, I accidentally left out two important things: other data members in the SessionMediator class.

The problem was that I had two additional members of the Tilemap class ("background_" and "foreground_"), which weren't being initialized in the constructor initialization list like the first member "map_".

The constructor should be changed to this:

SessionMediator()
    : map_(16,100,100), background_(1,1,1), foreground_(1,1,1)
{}

I apologize for any time wasted over this question; it turned out to be something much simpler. Hopefully someone else will see this question and realize the mistake they are making.

TPXL
  • 327
  • 1
  • 3
  • 12
0

The only thing I can think of is if you are using the copy constructor:

SessionMediator a = b; or SessionMediator a (b);

You might get in the situation where the default copy constructor of SessionMediator would try to use the default constructor of Tilemap which will cause the error you have.

tozka
  • 3,211
  • 19
  • 23
  • I'm creating the session mediator object as "SessionMediator session;", if that helps any. But I will look into that... – TPXL Oct 23 '12 at 19:45
  • Also check for forgotten colon, comma in the constructor or something like that, some spelling mistake. Also if they are defined in the same file, if `Tilemap` is declared after `SessionMediator` the compiler would not know about `TileMap` when it reach SessionMediator constructor and that might cause such an error. – tozka Oct 23 '12 at 20:00
0

Try to put map_(16u,100u,100u) in the SessionMediator constructor call to make the constants unsigned. This is the only thing that comes to mind now :-).

This compiles fine for me:

class Tilemap
{
public:
    Tilemap(const unsigned int tile_size, const unsigned int width, 
        const unsigned int height)
    {
    }
};

class SessionMediator
{
public:
    SessionMediator(): map_(16u,100u,100u){}

    Tilemap map_;
};
farfareast
  • 2,179
  • 1
  • 23
  • 22
  • This didn't work, but thanks for trying. I've been going over the code, I can't find any obvious syntax errors in either file. I'll let you guys know what the problem was if I find it though. – TPXL Oct 23 '12 at 21:02
-1

Well, when you do:

 Tilemap map_;

You're calling the default ctor - but you don't have one defined, that's the error message.

On the extra:

 Tilemap::Tilemap(const Tilemap&)

C++ generates a ctor that takes a reference for you. So the valid matches are (1) the one you defined which takes 3 args and (2) the auto-generated one that takes the const ref.

Mark Stevens
  • 2,366
  • 14
  • 9
  • 1
    When he writes `Tilemap map_;`, he is declaring a member. No constructor is called until the containing class constructor is called; in which case, the constructor of the member is called with the arguments given in the initialization list. – James Kanze Oct 23 '12 at 19:39
  • @TragicPixel: Ahhh subtle, when you intantiate B, it calls "B() : m_a(1,2,3)" - calling the 3 arg ctor for A; if you remove the ":m_a(1,2,3)" it should fail nicely ;-) – Mark Stevens Oct 23 '12 at 19:39
  • @MarkStevens But I'm instantiating map_ in the same exact way as I instantiate m_a: after instantiating SessionMediator, it calls "SessionMediator() : map_(1,2,3)" calling the 3 arg ctor for Tilemap. Which is exactly what is happening in the second example. – TPXL Oct 23 '12 at 19:48
  • @TragicPixel: Sorry, maybe it's a compiler difference, but both examples compile correctly for me with VS2010, and both fail to compile if I remove the call to the 3 argument ctor (with the "no appropriate default constructor" error). Sorry, I think I'm out of ideas. – Mark Stevens Oct 23 '12 at 19:59
  • Oh well. Thanks for the effort anyway! – TPXL Oct 23 '12 at 21:00