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

C++ 使用类属性值作为方法默认参数的替代方法?,c++,parameters,default-value,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 这是不可能的,因

我想实现这样的目标:

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()

(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似乎是唯一的选项


还有其他方法可以实现这一点吗?

这两个选项并不等同。使成员成为静态成员不应该是决定是否将其用作方法的默认值

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


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

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

   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
这就是我的意思:

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

允许在类外部访问“C++”、“代码> >代码> <强>私有/<强>数据,并打破基本C++规则。

如果您愿意更改接口,还有其他选择。您可以使用
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
}
但是带有指针的选项禁止使用右值作为函数的参数(即,您需要一个适当的变量来调用函数,您不能执行
foo(1)
,而是需要执行
int x=1;foo(&x);
,这是一种痛苦)

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

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

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

可以说这就是重载的目的;我猜使用指针和
nullptr
作为默认值不是一个选项?这太糟糕了,如果我想调用
foo(-1)
?在你开始被否决之前,我会删除这个。我实际上认为,在许多你知道特定值无效的领域,可以作为哨兵。例如,如果已知参数不是负值,则这将是一个选项。我也不会向上投票,但是+1来补偿可能是一个选项,这取决于域。@DavidRodríguez-dribeas,而不是为什么参数
不带符号的int
?@DavidRodríguez-dribeas这是非常违反直觉的。想象一下文档:传递任何整数值。如果希望使用成员
m_nVal
,请通过
-1
:|这个想法是好的,但在我的例子中,我不能因为Luchian提到的原因而依赖于使用硬编码值。但是谢谢你的帮助。Access不是这个构造的问题,你可以通过将字段公开来测试,在这种情况下,Access被授予,但它也不会编译。@Ajay这就是我开始考虑重构代码的原因-
m_nVal
当前是公开的,我想隐藏它。另一件事是,
foo
最常以
c.m_nVal
作为参数调用,所以我开始考虑使用它作为默认值……是的,但是私有和受保护是不允许的原因之一。不幸的是,Boost不是选项(不是我的决定);我喜欢指针的想法,但是,正如您所说的,这个接口在客户端看来并不自然(传递指针而不是对象本身);我同意超负荷,完全同意<代码>静态从一开始就不是一个选项。我在上面列出它只是因为它解决了一般问题(但不是在某些特定情况下,它不适合于类设计)。@BojanKomazec我会使用重载,其他一切对我来说似乎都是多余的。是的,这似乎是最直观的方法。谢谢你的帮助。
void foo( int *pval = 0 ) {
    int value = (pval? *pval : m_val);
    // use value from here on
}
void foo( int val ) {
   // actual implementation
}
void foo() {
   foo( m_val );
}