使用类属性值作为方法默认参数的替代方法?

Boj*_*zec 4 c++ parameters default-value

我希望实现这样的目标:

class C
{
    int m_nVal;
public:
    C(int nVal) : m_nVal(nVal){}            

    void foo(int nVal = m_nVal)
    {
         // use nVal, if provided; otherwise use m_nVal
    }
};

C c(1);
c.foo();  // use 1
c.foo(2); // use 2
Run Code Online (Sandbox Code Playgroud)

这是不可能的,因为C++标准说:

非静态成员不得在默认参数中使用

我有的选择是:

(1)超载foo():

class C
{
    int m_nVal;
public:
    C(int nVal) : m_nVal(nVal){}

    void foo()
    {
        // use m_nVal
    }

    void foo(int nVal)
    {
        // use nVal
    }
};
Run Code Online (Sandbox Code Playgroud)

(2)使用静态成员:

class C
{
    static int m_nVal;
public:         
    void foo(int nVal = m_nVal)
    {
        // use nVal, if provided; otherwise use m_nVal
    }
};
Run Code Online (Sandbox Code Playgroud)

我不想制作m_nVal静态成员,因此选项1似乎是唯一的一个.

有没有其他方法可以实现这一目标?

Dav*_*eas 6

如果您愿意更改界面,还有其他选择.你可以使用boost::optional:

// untested:
void foo( boost::optional<int> val = boost::optional<int>() ) {
    int value;
    if ( val ) value = *val;
    else value = m_val;
    // Now use `value` in the function
}
Run Code Online (Sandbox Code Playgroud)

如果你不能使用boost,你可以编写自己的可空包装器.您只需要存储type(int)和一个确定是否已设置的标志.

下一个选项是使用指针标记参数是可选的:

void foo( int *pval = 0 ) {
    int value = (pval? *pval : m_val);
    // use value from here on
}
Run Code Online (Sandbox Code Playgroud)

但是带指针的选项禁止使用rvalues作为函数的参数(即你需要一个适当的变量来调用函数,你不能这样做foo(1),而是需要做int x = 1; foo( &x );,这是一种痛苦).

最后,你可以使用你提供两个重载的方法,一个接受参数,一个不接受,只转发到第一个:

void foo( int val ) {
   // actual implementation
}
void foo() {
   foo( m_val );
}
Run Code Online (Sandbox Code Playgroud)

这实际上可能是最好的选择......