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

Alternatives to using class attribute value as a method default parameter?

本文关键字:方法 默认 参数 属性      更新时间:2023-10-16

我想实现这样的目标:

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

这是不可能的,因为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
    }
};

(2) 使用静态成员:

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

我不想让m_nVal成为静态成员,所以选项1似乎是唯一的。

还有其他方法可以做到这一点吗

如果您愿意更改接口,还有其他选择。您可以使用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
}

如果不能使用boost,可以编写自己的可为null的包装器。您只需要存储类型(int)和一个确定是否设置的标志。

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

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

但是带有指针的选项禁止使用右值作为函数的参数(即,您需要一个合适的变量来调用函数,您不能执行foo(1),而是需要执行int x = 1; foo( &x );,这有点痛苦)。

最后,您可以使用提供两个重载的方法,一个接受论点,另一个不接受论点,并转发到第一个:

void foo( int val ) {
   // actual implementation
}
void foo() {
   foo( m_val );
}

这可能是最好的选择。。。

这两个选项不等价。创建成员static不应该是决定是否将其用作方法的默认值。

如果m_nVal在逻辑上绑定到类,而不是实例,则将其设为static

如果m_nVal特定于类的每个对象,则不要,并使用第一个选项。

传递默认参数意味着编译器必须传递它。这意味着,对于m_nVal,编译器将使用this->m_nVal。这反过来意味着"foo(This->m_nVal);"。

这就是我的意思:

c.foo(c.m_nVal);  // use 1 

这将允许m_nVal私有数据在类外访问,并打破基本的C++规则。

   class C
    {
        int m_nVal;
    public:
        C(int nVal) : m_nVal(nVal){}            
        void foo(int nVal = -1)
        {
        if(nVal == -1)
            nVal = m_nVal;
             // use nVal, if provided; otherwise use m_nVal
        }
    };
C c(1);
c.foo();  // use 1
c.foo(2); // use 2