我正在实现一个名为 CurrentUser 的成员函数。它将用户名作为参数并返回与给定用户名匹配的用户实例对象。下面是代码
User& UserDB::currentUser(string username){
// userlists is a instance member which is list of user objects
for(list<User>::iterator i = userlists.begin(); i != userlists.end(); ++i)
{
if(*i.getName().compare(username)==0){
return *i;
}
}
return null;
}
不确定这样做是否正确。如果错了,请纠正我。谢谢!
更新:嘿伙计们感谢您的建议,我找到了一种通过返回用户指针来做到这一点的方法。这是代码。
User* UserDB::currentUser(string username){
for(list<User>::iterator i = userlists.begin(); i != userlists.end(); ++i)
{
if(i->getName().compare(username)==0){
return i;
}
}
return null;
}
有几种方法可以干净利落地做到这一点。
你当然可以返回一个指针,但这会让人们感到惊讶,因为返回一个引用或一个对象更为正常。指针给对象消费者带来了很多问题,例如:
如果它为空,我应该得出什么结论?
我应该删除它吗?
等等。
返回对某物或某物的引用可以消除这些歧义。
话虽如此,引用不能为空,因此函数必须返回一些东西。如果它没有找到它正在寻找的项目,它必须向调用者表明这一点。一种方法是异常(exception)(即要求该项目在逻辑上是不正确的)。但是,如果元素不存在是正常现象,那么您不想强制您的消费者处理异常 - 这也是一种糟糕的形式。
所以答案是返回一个封装了可选引用的对象。
一个很好的例子是 boost::optional<User&>
但如果您不想包含 boost,那么自己动手也很简单:
struct optional_user
{
using element_type = User;
using reference_type = element_type&;
optional_user() : _p(nullptr) {}
optional_user(reference_type r)
: _p(std::addressof(r))
{}
bool valid() const { return bool(_p); }
// compares to true if the user is present, false otherwise
operator bool() const { return valid(); }
reference_type value() const {
assert(_p);
return *_p;
}
// can be used anywhere a User& is required
operator reference_type () const {
return value();
}
private:
element_type* _p = nullptr;
};
现在你的函数变成了:
optional_user UserDB::currentUser(string username)
{
typedef list<User>::iterator Iter;
for(Iter i = userlists.begin(); i != userlists.end(); ++i)
{
if(i->getName().compare(username)==0)
{
return optional_user(*i);
}
}
// return an indicator that the user is not present
return optional_user();
}
并且您的调用站点变为:
optional_user = users.currentUser("bob");
if (optional_user) {
do_something_with(optional_user /* .value() */);
}
我是一名优秀的程序员,十分优秀!