Using a class member as a default argument for a member function

馋奶兔 提交于 2019-12-03 17:39:28

问题


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?

回答1:


[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.




回答2:


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.




回答3:


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
    }
  }


来源:https://stackoverflow.com/questions/26999739/using-a-class-member-as-a-default-argument-for-a-member-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!