使用类成员作为成员函数的默认参数

时间:2014-11-18 16:57:54

标签: c++ c++11 default-value overloading

除了手动重载相应的成员函数并以成员作为参数调用第一个重载之外,还有其他方法吗?

我正在尝试按照

的方式行事
class test
{
    string t1="test";

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

(测试它:http://goo.gl/36p4CF

目前我猜没有技术上的原因,为什么这不起作用。

  • 除了重载和手动设置参数外,是否有这样的解决方案?
  • 为什么这不起作用,是否有技术原因?

3 个答案:

答案 0 :(得分:17)

[dcl.fct.default] / 8:

  

关键字this不得用于成员函数的默认参数。

这是一个普遍问题的特例:您不能在参数的默认参数中引用其他参数。即。

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

是不正确的。那就是

class A
{
    int j;
};

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

这基本上是编译器将void f(int i = j) {}形式的成员函数转换为的内容。这源于以下事实:函数参数的评估顺序和后缀表达式(构成对象参数)未指定。 [dcl.fct.default] / 9:

  

每次调用函数时都会计算默认参数。   未指定函数参数的评估顺序。因此,默认情况下不应使用函数的参数   参数,即使它们没有被评估。

答案 1 :(得分:2)

  

除了重载和手动设置参数外,是否有这样的解决方案?

不,如果您希望默认参数依赖于另一个参数(包括this),则需要重载。虽然,在这种情况下,它没有意义,因为这是一个构造函数,并且t1在被调用之前不存在。

  

为什么这不起作用,是否有技术原因?

因为未指定函数参数的评估顺序。要允许默认参数中的参数值,您需要更复杂的规则来确保每个参数在使用前都已初始化。

答案 2 :(得分:1)

你还没有说出你想要达到的目标。我假设您需要每个实例以特定方式做出反应,具体取决于某个类变量。

但是,如果您不需要按实例行为,则可以使用静态变量。以下作品:

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

...这意味着类test的所有对象都将使用静态字符串t1作为其默认值。

你可以“破解”一点,并将其用作丑哨的哨兵:

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