在C++中,当我们通过引用传递参数时,是否可以给函数的参数设置默认值。
例如,当我尝试声明一个函数:
virtual const ULONG Write(ULONG &State = 0, bool sequence = true);
当我这样做时,它会出现错误:
错误 C2440:'default argument':无法将 'const int' 转换为 'unsigned long &' 不能将非lvalue的引用绑定到非const
在C++中,当我们通过引用传递参数时,是否可以给函数的参数设置默认值。
例如,当我尝试声明一个函数:
virtual const ULONG Write(ULONG &State = 0, bool sequence = true);
当我这样做时,它会出现错误:
错误 C2440:'default argument':无法将 'const int' 转换为 'unsigned long &' 不能将非lvalue的引用绑定到非const
你可以使用const引用来实现,但不能使用非const引用。这是因为C++不允许将临时对象(在这种情况下是默认值)绑定到非const引用。
解决这个问题的一种方法是使用实际的实例作为默认值:
static int AVAL = 1;
void f( int & x = AVAL ) {
// stuff
}
int main() {
f(); // equivalent to f(AVAL);
}
但这在实际应用中非常有限。
已经在对你的回答的一个直接评论中提到过了,但是为了正式说明。你想要使用的是重载:
virtual const ULONG Write(ULONG &State, bool sequence);
inline const ULONG Write()
{
ULONG state;
bool sequence = true;
Write (state, sequence);
}
使用函数重载还有其他好处。首先,您可以默认任何想要的参数:
class A {};
class B {};
class C {};
void foo (A const &, B const &, C const &);
void foo (B const &, C const &); // A defaulted
void foo (A const &, C const &); // B defaulted
void foo (C const &); // A & B defaulted etc...
在派生类中重新定义虚函数的默认参数是可能的,而避免了重载:
class Base {
public:
virtual void f1 (int i = 0); // default '0'
virtual void f2 (int);
inline void f2 () {
f2(0); // equivalent to default of '0'
}
};
class Derived : public Base{
public:
virtual void f1 (int i = 10); // default '10'
using Base::f2;
virtual void f2 (int);
};
void bar ()
{
Derived d;
Base & b (d);
d.f1 (); // '10' used
b.f1 (); // '0' used
d.f2 (); // f1(int) called with '0'
b.f2 (); // f1(int) called with '0'
}
仅有一种情况需要使用默认值,那就是在构造函数中。无法从另一个构造函数中调用一个构造函数,因此这种技术在那种情况下不能工作。
d.f2(); // 调用带有参数'0'的f2(int)函数 b.f2(); // 调用带有参数'0'的f2(int)函数
- Pietro还有一种旧的C方法提供可选参数:使用指针,当参数不存在时可以为NULL:
void write( int *optional = 0 ) {
if (optional) *optional = 5;
}
template<typename T> class ByRef {
public:
ByRef() {
}
ByRef(const T value) : mValue(value) {
}
operator T&() const {
return((T&)mValue);
}
private:
T mValue;
};
那么您将能够:
virtual const ULONG Write(ULONG &State = ByRef<ULONG>(0), bool sequence = true);
ByRef
的实例在内存中存在于哪里?它不是一个临时对象,在离开某个范围(比如构造函数)时会被销毁吗? - Andrew Cheongstruct Foo {
virtual ULONG Write(ULONG& State, bool sequence = true);
};
Foo f;
ULONG s = 5;
f.Write(s); // perfectly OK, because s is a real variable
f.Write(0); // compiler error, 0 is not a real variable
// if the value of 0 were changed in the function,
// I would have no way to refer to the new value
State
,你可以将其改为const ULONG&
。但这样做对性能提升帮助不大,所以我建议把它改成非引用ULONG
。我注意到你已经在返回ULONG
,我有一个狡猾的想法,即其值是任何必要修改后的State
的值。如果是这种情况,我会将方法声明如下:// returns value of State
virtual ULONG Write(ULONG State = 0, bool sequence = true);
不,这是不可能的。
按引用传递意味着函数可能会更改参数的值。如果参数不是由调用者提供的,并且来自默认常量,那么函数应该更改什么?
你不能使用常量字面值作为默认参数,原因与将其用作函数调用的参数相同。引用值必须具有地址,而常量引用值不需要(即它们可以是r-values或常量字面值)。
int* foo (int& i )
{
return &i;
}
foo(0); // compiler error.
const int* bar ( const int& i )
{
return &i;
}
bar(0); // ok.
int null_object = 0;
int Write(int &state = null_object, bool sequence = true)
{
if( &state == &null_object )
{
// called with default paramter
return sequence? 1: rand();
}
else
{
// called with user parameter
state += sequence? 1: rand();
return state;
}
}
我曾多次使用这种模式,其中有一个参数可以是变量或null。传统的方法是让用户传递一个指针来处理这种情况。如果他们不想填充值,则传递一个NULL指针。我喜欢使用null对象方法。它使调用者的生活更加轻松,而不会过于复杂化被调用者的代码。
另一种方法可能是以下方式:
virtual const ULONG Write(ULONG &State, bool sequence = true);
// wrapper
const ULONG Write(bool sequence = true)
{
ULONG dummy;
return Write(dummy, sequence);
}
那么以下调用是可能的:
ULONG State;
object->Write(State, false); // sequence is false, "returns" State
object->Write(State); // assumes sequence = true, "returns" State
object->Write(false); // sequence is false, no "return"
object->Write(); // assumes sequence = true, no "return"
void f(const double& v = *(double*) NULL)
{
if (&v == NULL)
cout << "default" << endl;
else
cout << "other " << v << endl;
}
在面向对象编程中,如果说一个类有一个“默认值”,那么这个默认值必须被相应地声明,然后可以作为默认参数使用,例如:
class Pagination {
public:
int currentPage;
//...
Pagination() {
currentPage = 1;
//...
}
// your Default Pagination
static Pagination& Default() {
static Pagination pag;
return pag;
}
};
在你的方法中...
shared_ptr<vector<Auditoria> >
findByFilter(Auditoria& audit, Pagination& pagination = Pagination::Default() ) {
这个解决方案非常适合,因为在这种情况下,“全局默认分页”是一个单一的“参考”值。您还可以像“全局级别”的配置一样在运行时更改默认值,比如用户分页导航偏好等。