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

16

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

我正在尝试类似以下方式:

class test
{
    string t1="test";

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

(测试一下:http://goo.gl/36p4CF)

目前我猜想这种方式在技术上没有不可行的原因。

  • 除了过载和手动设置参数,还有没有其他方法可以解决这个问题?
  • 为什么这样做不起作用,是否存在技术上的原因?

只需使用“test”,它不会降低性能或增加内存使用量,因为它将是常量。 - Ryan
@self:但是t1不是常量;因此用一个常量值替换它不一定会做同样的事情。 - Mike Seymour
我是指使用字符串字面值“test”。 - Ryan
1
@self:是的,我知道。这不会与发布的代码意图相同,该代码的意图是使用成员变量的当前值,而不是常量值。 - Mike Seymour
“Test it”链接非常失形。您正在使用构造函数作为测试函数,这似乎不是一个好主意。而且该函数修改参数,但您使用“const char *”(文字字符串)调用它。在提供MCVE时要更加小心。 - MariusSiuram
是的,抱歉,我匆忙回答。我会修复的。 - thi gg
3个回答

20

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

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


是的,我看到问题了。但是语法糖应该很好用 ;) - thi gg
@thigg 不能否认:D 在你的情况下,重载应该可以通过合理的可读性来完成工作。 - Columbo
是的,但我必须为几个函数做这个,所以很烦人 ;) - thi gg

3

除了重载和手动设置参数,这种方法还有解决方案吗?

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

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

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


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

1
@thigg 免责声明:您并没有说明您想实现什么。是的,我无法理解您的需求,只是想在“静态”和非“静态”之间提供一些见解。好的,我会稍微修改我的回答,但我认为对于那些阅读您的问题的人来说,它仍然是有用的。 - MariusSiuram
1
是的,也许对于正在寻找的人来说很好。总体而言,我想这里非常有教育意义。 - thi gg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接