Using a class member as a default argument for a m

2020-06-03 04:05发布

Is there another way than manually overloading the corresponding member function and calling the first overload with the member as the argument?

I am trying something along the lines of

class test
{
    string t1="test";

    testfun( string& val = this->t1 )
    { /* modify val somehow */ }
};

(Test it: http://goo.gl/36p4CF)

Currently I guess there is no technical reason why this should not work.

  • Is there a solution doing it this way except overloading and setting the parameter manually?
  • Why is this not working, is there a technical reason for it?

3条回答
一夜七次
2楼-- · 2020-06-03 04:22

You haven't said what you want to achieve. I assume that you need that each of your instances react on a specific way, depending on a certain class variable.

However, if you don't need a per-instance behaviour, then you can use static variables. The following works:

#include <iostream>
using namespace std;
struct test {
  static string t1;  
  void say(const string &val=t1){
    cout << val << "!" << endl;
  }
};

string test::t1;

int main() {
   cout << "Hello World" << endl; 
   test::t1 = string("asd");
   test a;
   a.say();
   a.say("bla");
   test::t1 = string("blahblah");
   a.say();
   return 0;
}

... which means that all the objects of the class test will use the static string t1 as their default value.

You can "hack" a little bit, and use this as an ugly sentinel:

  void say(const string &val=t1){
    if (&val == &t1) {
      // They are using the default value, so act as you want
    } else {
      // they are providing a value
    }
  }
查看更多
老娘就宠你
3楼-- · 2020-06-03 04:35

[dcl.fct.default]/8:

The keyword this shall not be used in a default argument of a member function.

This is a special case of a general problem: You cannot refer to other parameters in a default argument of a parameter. I.e.

void f(int a, int b = a) {} 

Is ill-formed. And so would be

class A
{
    int j;
};

void f(A* this, int i = this->j) {}

Which is basically what the compiler transforms a member function of the form void f(int i = j) {} into. This originates from the fact that the order of evaluation of function arguments and the postfix-expression (which constitutes the object argument) is unspecified. [dcl.fct.default]/9:

Default arguments are evaluated each time the function is called. The order of evaluation of function arguments is unspecified. Consequently, parameters of a function shall not be used in a default argument, even if they are not evaluated.

查看更多
Melony?
4楼-- · 2020-06-03 04:39

Is there a solution doing it this way except overloading and setting the parameter manually?

No, you'd need an overload if you want a default argument to depend on another parameter, including this. Although, in this case, it doesn't make sense since this is a constructor, and t1 doesn't exist before it's called.

Why is this not working, is there a technical reason for it?

Because the evaluation order of function arguments isn't specified. To allow parameter values in default arguments, you'd need much more complex rules to ensure each parameter was initialised before being used.

查看更多
登录 后发表回答