我想实现这样的目标:
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似乎是唯一的一个。
还有其他方法可以实现这一目标吗?
答案 0 :(得分: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
}
如果你不能使用boost,你可以编写自己的可空包装器。您只需要存储类型(int
)和一个确定是否已设置的标志。
下一个选项是使用指针标记参数是可选的:
void foo( int *pval = 0 ) {
int value = (pval? *pval : m_val);
// use value from here on
}
但是带指针的选项禁止使用 rvalues 作为函数的参数(即你需要一个适当的变量来调用函数,你不能做foo(1)
而是需要做int x = 1; foo( &x );
,这有点痛苦。)
最后,您可以使用提供两个重载的方法,一个接受参数,一个不接受,只转发到第一个:
void foo( int val ) {
// actual implementation
}
void foo() {
foo( m_val );
}
这实际上可能是最好的选择......
答案 1 :(得分:2)
这两个选项并不相同。成员static
不应该决定是否要将其用作方法的默认值。
如果m_nVal
在逻辑上绑定到类而不是实例,请将其设为static
。
如果m_nVal
特定于班级的每个对象,请不要使用第一个选项。
答案 2 :(得分:0)
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
答案 3 :(得分:0)
传递默认参数意味着编译器必须传递它。这意味着,对于m_nVal
,编译器将使用this->m_nVal
。反过来,这将意味着`foo(this-&gt; m_nVal);'。
这就是我的意思:
c.foo(c.m_nVal); // use 1
允许在类外部访问m_nVal
私有数据,并打破基本的C ++规则。