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