set default parameter to a member variable

Viewed 127

I tried to set a default parameter to a member variable, it gave me this bug.

[cquery] invalid use of non-static data member 'num'

code

#include <iostream>
class Test{
   private:
      int val = 0;
   public:
      void print_num(int num = val){
         std::cout << num << '\n';
      }
}
int main(){
   Test test;
   test.print_num();
   return 0;
}
3 Answers

Despite it being quite obvious what this would mean, you just can’t. The usual workaround is to provide an overload that (implicitly) uses this to get the member value.

In order to set a default value for a function parameter to a class member, the member must be static.

Citing the documentation,

Non-static class members are not allowed in default arguments

However, given the context of your code sample I doubt this is what you want to do (as every instance of Test class will point to the same val. Citing the docs:

Static members of a class are not associated with the objects of the class: they are independent variables

If you make val static in your example, and have multiple instances of Test in use by your code, you can (and very likely will) have some unexpected behavior. Consider:

#include <iostream>
class Test{
   private:
      static int val;
   public:
      void print_num(int num = val){
         std::cout << num << '\n';
      }
      void set_val(int num) {
          val = num;
      }
}
int Test::val = 0;
int main(){
   Test test1;
   test1.set_val(1);
   Test test2;
   test2.set_val(2);
   test1.print_num(); // results in "2"
   return 0;
}

A better alternative would be to pass a pointer to your function like this:

#include <iostream>
class Test{
   private:
      int val = 0;
   public:
      void print_num(int* numptr = nullptr){
         int num = (numptr ? *numptr : val);
         std::cout << num << '\n';
      }
}
int main(){
   Test test;
   test.print_num();
   return 0;
}

Or, as described by Davis Herring, use an overload:

#include <iostream>
class Test{
   private:
      int val = 0;
   public:
      void print_num(int num){
         std::cout << num << '\n';
      }
      void print_num() {
        return print_num(val); // return is irrelevant here, but my preferred coding style
      }
}
int main(){
   Test test;
   test.print_num();
   return 0;
}

Edited to reflect the comment and example.

Your function definition doesn't actually know what val is because it doesn't actually live inside of your class. The compiler is actually making a function that contains your class as a parameter and abstracts away all of that. You'll want to set num to val within the function body.

Related