2

Why are my default/optional parameters being ignored?

grid_model.h

class GridModel {
public:
        GridModel();
        void PrintGrid(bool);
};

grid_model.cpp

void GridModel::PrintGrid(bool flag = false) {
    // things...
}

grid_model_test.cpp

ns::GridModel* gm = new GridModel();
gm->PrintGrid(true); // works
gm->PrintGrid(); // doesn't work

error:

grid_model_test.cpp:22:12: error: no matching function for call to ‘ns::GridModel::PrintGrid()’
  gm->PrintGrid();
                 ^
In file included from grid_model_test.cpp:2:0:
grid_model.h:27:7: note: candidate: void ns::GridModel::PrintGrid(bool)
  void PrintGrid(bool);
       ^~~~~~~~~

When I use them elsewhere, they seem to work fine.

#include <iostream>

class Thing {
public:
        void Whatever(bool);
};

void Thing::Whatever(bool flag = false) {
        std::cout << "Parameter was: " << flag << std::endl;
}

int main() {
        Thing* thing = new Thing();
        thing->Whatever();
        return 0;
}
Alexander Kleinhans
  • 5,950
  • 10
  • 55
  • 111
  • If the test code only sees the header, it will not know about the default parameter. – Bo Persson Mar 26 '18 at 00:49
  • While I don't think this is a bad question, I think you could improve it slightly but mentioning that it doesn't work when the declaration and definition appear in separate files, but works when they're in the same file (since that is what differs in your two cases here). Of course you may not have realised that was the issue, in which case you can leave it as is. A slight improvement would be removing the `= new`, and just using more simple and correct code (i.e. `Thing t; t.Whatever();`). – Tas Mar 26 '18 at 00:59

1 Answers1

3

Default parameter values should, as a good design practice, be placed in the declaration, not in the implementation:

class GridModel {
public:
        GridModel();
        void PrintGrid(bool flag=false);
};

void GridModel::PrintGrid(bool flag) {
    // things...
}

Technically (as described in more length here http://en.cppreference.com/w/cpp/language/default_arguments ): the default arguments must be visible in the translation unit where the call is made. If you split the class in a grid_model.h and grid_model.cpp, any other .cpp (such as grid_model_test.cpp) that includes grid_model.h will not be aware of information that is only present in grid_model.cpp.

FBergo
  • 1,010
  • 8
  • 11
  • 1
    Although covered in the mentioned duplicate, it may be worth mentioning _why_ it works in the second example but not the first. – Tas Mar 26 '18 at 00:53
  • I edited the answer to clarify it, thanks. – FBergo Mar 26 '18 at 01:03